FC2ブログ


スマフォのアプリを作りたい(24):サーバ側の仕掛けを作る①

   プログラミング [2020/05/13]
スマフォだけで全て完結するシステムって言うのはなかなかねー。
一人だけで使うアプリならありそうだけど・・・
複数の人で、データを共有したいとなったら、当然間を取り持つサーバーが必要になります。

今回作っているアプリも基本、チャットの機能だし。
さらに、データが蓄積させたり、利用内容が高度になれば、DBも必要です。

なので、DBを使ったシステムということで、その動作環境とサーバ側アプリ(スクリプト)を作成します。


ちょっとだけやったことがある言語と言えば
・ASP(古い。その実VB)
・PHP(これも古いが最近も使った)
・Perl(もう懲り懲り)

既にEclipseの環境があるので当然PHPを選びました。
DBはMySQLです。

始めます。


◆プロジェクトの作成
この辺の手順は、以前の備忘録Eclipse-PHP環境でちょっとハマった辺りが何かの足しになるかもしれません。そちらを参考にされてください。

ともかくPHPのプロジェクトを新しく作ります。
ソースはまだ何も入ってません。


◆DBの作成
参考:https://blog.goo.ne.jp/xmldtp/e/8cf1d195d8f18661884b7c1c90cca0c4
1)Eclipseのメニューから
-[ウィンドウ]-[パースペクティブを開く]-[その他]を選択
-続けて、「パースペクティブを開く」ウィンドウで、[データベース開発]を選択
-Eclipse画面の左側が、「データ・ソース・エクスプローラー」に変わります。
2)データベース接続
-「データ・ソース・エクスプローラー」の[データベース接続]を右クリックして
-プルダウンから[新規]を選択
-「新規接続プロファイル」上のリストから「MySQL」を選択して[次へ]をクリック


-ファイル選択ダイアログでJDBCを指定?・・・

あれ?こんなに面倒くさかったかしら。
以前にもDBの作成はやってみたことがあったはずなのに、全くこの手順に馴染みがありません。

・・・

続きを読む

スポンサーサイト





スマフォのアプリを作りたい(23):実際のスマフォでアプリを試す

   プログラミング [2020/04/27]
これまで、ずーーっとエミュレータ(AVD:Android Virtual Device)でしか試作したアプリを動作させてませんでした。
そもそも、エミュレータを使っていたのは、買った中古のSIMフリー・スマフォのAndoridバージョンが古くて対象として使えなかったから。
富士通 ARROWS Me F-11D Android4.0 APIレベル15

APIレベル15だとVisualStudio2017(NDK)ではサポートされてなかった。
たしかAPIレベル19以降だったかと思う。

一方、React Nativeに切り替えたときには、もうエミュレータを使うことしか頭になくて。
エミュレータの最低の前提バージョンが、6.0(APIレベル23)。

ずっと、それで動作確認してきたが、そろそろ実機を使ってみたくなった。

ここで、倅が以前使っていたLUMIXというスマフォが引き出しから出てきた。
確認してみると、Androidバージョンは、4.04となっている。
もしかしたら使えるかも。

ただ、4.0xのコード名がIceCreamSandwichです。それに対して4.1-4.3がJellyBeanという名前。
どっかの機能制限で、「JellyBean以降」というのがあった気がします。

まあ、どうなるかやってみます。


◆SDKの追加インストール
Android SDKとしては、かなり古いバージョンのものまで用意されていたはずなので、SDKの追加インストールから。

-AndroidStudioを起動
-Welcome画面の右下の[Configure]をクリックして、プルダウンから「SDK Manager」を選択
-各SDKの選択画面が表示されます。すでにインストールしてある10.0と6.0にチェックが入ってます。
-「SDK 4.0.3(IceCreamSandwich)」をチェック
-右下の「Show Package Detail」をチェック
-「SDK 4.0.3」の構成が確認できます。
-全部にチェックが入ってるのをそのままにしました。
-一応「SDK Tools」タブを確認しましたが、何か追加要かわからなかったのでここもそのまま
-右下の[OK]ボタンをクリック
-インストールが完了(Done)したようなので、[Finish]をクリック


◆スマフォのPCへの接続
LUMIXの場合
-スマフォ(LUMIX)の画面下のボタンの左側(三本線のマーク下)を押す
-プルアップメニューから「本体設定」を選択
-設定メニューの一番下の方の「開発者向けオプション」を選択
-「注意」メッセージが表示されるのでよく読んでから[OK]をタップ
-「USBデバッグ」項目をチェック状態にします。
 (その他の項目はご自由に)

チャント接続可能かどうかは、以下で確認するのだそうです。
参考:https://reactnative.dev/docs/running-on-device

-コマンドプロンプトを起動します。
-カレントドライブをSDKインストール先の「platform-tools」にします。
-「adb devices」コマンドを打ち込んで、表示内容に「xxxxxxxxxxx device」が出るか確認します。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\android\sdk\platform-tools

d:\AppMake\Android\Sdk\platform-tools>adb devices
* daemon not running; starting now at tcp:5037
* daemon started successfully
List of devices attached
5C84000600000001 device
---------------------------------------------------


参考(React Native)サイトの説明では、このあと「react-native run-android」をやればいいように書かれています。
それだと、エミュレータが起動されちゃうんじゃ?
「adb -s (デバイス名) reverse tcp:8081 tcp:8081」とやるとありますが、「デバイスがAndroid5.0以降を実行していて」とあります。
じゃ、それより前のバージョンのデバイスはどうするの?
なんで、こういう説明の仕方しかしないのかなー。ちょっとイラつきますよね。

あと、ベースのSDKを変更する部分の設定がまだです。


◆プロジェクトのベースSDKの変更
「どこで、対象Androidのバージョンを決めてたっけ?」と考えて、過去の書き込みを自身で読み返してみました。
(このブログを備忘録として使ってます。)

これかな?
「スマフォのアプリを作りたい(14):音声認識させたい②」
react-native-google-speech-apiを導入しようとしたときに、ビルドが通らなかった原因が、android\build.gradleの中に指定してあった、「minSdkVersion = 16」という記述。
この辺の指定で、四苦八苦したのをジワジワ思い出してきた。

ってことは、
その時ダメだったAPIレベルより低いものを指定して、ビルドが通る分けがない。
でも、試しにやってみた。
----build.gradle-----------------------------------

buildscript {
ext {
buildToolsVersion = "28.0.3"
//*** changed min_version for google-speech-api by sarumosunaru
//minSdkVersion = 16
//minSdkVersion = 21
//compileSdkVersion = 28
//targetSdkVersion = 28
//*** try old api level
minSdkVersion = 15
compileSdkVersion = 15
targetSdkVersion = 15
}


---------------------------------------------------


見事に、エラーが出まくりました。
----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>react-native run-android
info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag.
Jetifier found 1034 file(s) to forward-jetify. Using 4 workers...
info Starting JS server...
info Installing the app...

> Configure project :react-native-audio
WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
WARNING: minSdkVersion (16) is greater than targetSdkVersion (15) for variant "debug". Please change the values such that minSdkVersion is less than or equal to targetSdkVersion.
WARNING: minSdkVersion (16) is greater than targetSdkVersion (15) for variant "release". Please change the values such that minSdkVersion is less than or equal to targetSdkVersion.

> Configure project :react-native-google-speech-api
The com.google.protobuf plugin was already applied to the project: :react-native-google-speech-api and will not be applied again after plugin: android-library
WARNING: API 'variant.getJavaCompile()' is obsolete and has been replaced with 'variant.getJavaCompileProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getJavaCompile(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.

> Task :react-native-audio:compileDebugJavaWithJavac

> Task :react-native-audio:compileDebugJavaWithJavac FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.5/userguide/command_line_interface.html#sec:command_line_warnings
28 actionable tasks: 6 executed, 22 up-to-date
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\AudioRecorderManager.java:87: error: diamond operator is not supported in -source 1.6
Map constants = new HashMap<>();
^
(use -source 7 or higher to enable diamond operator)
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\AudioRecorderManager.java:277: error: multi-catch statement is not supported in -source 1.6
} catch (InvocationTargetException | RuntimeException | IllegalAccessException e) {
^
(use -source 7 or higher to enable multi-catch statement)
D:\AppMake\proj\VTChat\node_modules\react-native-audio\android\src\main\java\com\rnim\rn\audio\ReactNativeAudioPackage.java:22: error: diamond operator is not supported in -source 1.6
List modules = new ArrayList<>();
^
(use -source 7 or higher to enable diamond operator)

3 errors

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native-audio:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.


---------------------------------------------------

前の方のreact-native-audioのエラーは明らかにAPIレベルが合ってないという感じですかね。
後の方は、Javaのバージョンが合ってないから?TypeScript記述?でエラーになってます。

ここで、Android/APIレベル/Javaのバージョンの関係について、ちょっと気になったのでぐぐって見ました。
参考:https://so-zou.jp/software/tech/programming/java/introduction/version/
参考:https://development.relaxes.jp/android%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%80%81api%E3%83%AC%E3%83%99%E3%83%AB%E3%80%81%E3%82%B3%E3%83%BC%E3%83%89%E3%83%8D%E3%83%BC%E3%83%A0%E4%B8%80%E8%A6%A7/

なんか、Javaのバージョンってややこしい。
たぶん、スマフォはAndroid4.0(APIレベル15)-Java1.6 で、
さるの現状の環境はJDK8(Java1.8)だから確かに合ってない。

----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>java -version
Picked up _JAVA_OPTIONS: -Duser.language=en
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
---------------------------------------------------


まあでも、ここを何とか切り抜けたとしても、その先の見通しもない気がします。
なので、この前提不一致の件の対策方法を探るのはやめて、build.gradleは元の記述に戻します。

続いて・・・

続きを読む



スマフォのアプリを作りたい(22):音声ファイル(.m4a)を再生する

   プログラミング [2020/04/16]
前々回までに音声認識と同時にその音声を録音する機能を作りました。
録音した音声は、.m4aファイルとして、保存してあります。
その音声ファイルを再生する部分をやってみます。

いつものボヤキに入る前に。

「スマフォのアプリを作りたい」シリーズを最初から読まないとどういう環境でやってることなのか分からないかと思いますので、ここでさらっと説明しておきます。
React Nativeを開発環境としています。
 開発環境のmustな前提/構成については省略します。
 スマフォのアプリを作りたい(2)~(4)辺りには書いてあります。
-最初のターゲットとしてはAndroidスマフォとうことにしています。
-動作環境は、AndroidStudioのAVD(エミュレータ)を現状は使用しています。
 (未だ実機での動作を一切確認したことがありません。)
Build、Load&Goは、「react-native run-android」コマンドで行っています。
-デバッガは、Chromeのデベロッパーツールです。
-コードの編集は、sakuraを使っちゃってます。つまり、AndroidStudioは使ってません。
 (使い方を現時点で知りません。)
-パッケージ(Javaコード)に手を入れてしまった場合は、デバッガは使ってなくて、
 logcatのメッセージログを使ってます。
-これらの開発・動作環境を全てタブレットPC(+SSD増設HDD)に突っ込んでます。
-OSはWindows10です。
-外部との接続は、主にポケットWifiです。

かなり、素朴なやり方ですかね。
そもそも、タブレットPCなので、そんなにパワーはなくて、サクサクというわけには行きません。
「react-native run-android」がかなりか確率で失敗するので、効率は良くありません。
また、Chromeでのデバッグもとっても重い印象です。
でも、「持って歩ける開発環境」です。

では、本題に入りましょう。


◆音声ファイルの再生には何を使う?
ちょっと前に、「録音」に関しては「react-native-audio」を使いかけました。
これで、「再生」もできるのかと思いきや・・・録音だけの機能なんだそうです。
再生」は、「react-native-sound」を使うのが、どうも定番っぽい?

でも、.m4aは再生できるんでしょうか?
ちょっとぐぐってみました。
参考:http://www.npmjs.com/package/react-native-sound
本家?Ver.1.11.0では、アルファ版だからバグがあるかもしれないよと書いてます。
また、ストリーミング再生はサポートしてないとある。
.m4aが扱えるのかは、上記URLのページ内には書かれていない。
んーー。

一方、以下のサイトには「.m4a」の単語が含まれていました。
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
タイトルからしてファイル再生とストリーミングもできるっぽい。
パッケージ名はちょっと長くなって」「react-native-sound-player」だそうです。
.m4aがサポートされているかどうかは、Android本家のサイトにリンクがされてあって、
参考:https://developer.android.com/guide/topics/media/media-formats
サポートされてるっぽいぞ。

ちなみに「AVPlayer(iOS)」と書かれている方(リンク先がなぜかstackoverflowのページ)では・・・
iOSのバージョン次第ってことなんでしょうか。10.9.1で問い合わせたときのリストには「public.mpeg-4-audio」がある。
まあ、そっちはまた後で考えるということで。

さるがこの手のページに慣れて来たせいもあって、説明も割と分かりやすいという第一印象。
なので、react-native-sound-playerを使ってみます。


◆追加インストール
参考:https://reactnativeexample.com/play-or-stream-audio-files-in-reactnative-on-ios-android/
に従ってインストールしてみます。

いつもの通りプロジェクトフォルダにカレントを移動して「npm install ・・・」と
いつもと違う「react-native link ・・・」を実行します。(でも、実は実行しなくてよかった。
----コマンドプロンプト-----------------------------
:
D:\AppMake\proj\VTChat>npm install react-native-sound-player --save
npm WARN @typescript-eslint/eslint-plugin@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/parser@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.


+ react-native-sound-player@0.10.4
added 1 package from 1 contributor and audited 957490 packages in 64.888s


D:\AppMake\proj\VTChat>react-native link react-native-sound-player
info Linking "react-native-sound-player" iOS dependency
info iOS module "react-native-sound-player" has been successfully linked
info Linking "react-native-sound-player" Android dependency
info Android module "react-native-sound-player" has been successfully linked
---------------------------------------------------

何事もなく成功したようです。

ですが、「react-native run-android」したときに以下のエラーが出ました。
----コマンドプロンプト-----------------------------
D:\AppMake\proj\VTChat>react-native run-android
error React Native CLI uses autolinking for native dependencies, but the following modules are linked manually:
- react-native-fs (to unlink run: "react-native unlink react-native-fs")
- react-native-sound-player (to unlink run: "react-native unlink react-native-sound-player")
This is likely happening when upgrading React Native from below 0.60 to 0.60 or above. Going forward, you can unlink this dependency via "react-native unlink " and it will be included in your app automatically. If a library isn't compatible with autolinking, disregard this message and notify the library maintainers.
---------------------------------------------------

もし、さると同じように、サイトの説明を斜めに読んで「react-native link ・・・」を実行してしまった場合は、「react-native unlink ・・・」を実行するとエラーは消えます。

さるにとって「link」というパラメタ指定は鬼門のようです。

あと、本題には関係ないですが、録音音声のファイルリストを表示するために「react-native-fs」をインストールします。
手順としては、「npm install react-native-fs --save」を実行するだけです。
※本家のサイト等に「react-native link react-native-fs」を実行するように書いてありますが、さるの環境では必要ないらしい。また、本家サイトのUsageには、settings.gradle等に何か修正を加えるような記述が書かれているけど、DocumentDirectory以外をアクセスする場合に必要な設定なのかな? 幸いにして今回扱う録音ファイルはDocumentDirectory下なので必要ないはず。


それでは、実装に入ります・・・

続きを読む



スマフォのアプリを作りたい(21):メニュー作成の一例

   プログラミング [2020/04/08]
チャットと音声認識を組み合わせたくて、React Nativeでチャット(react-native-gifted-chat)と音声認識(react-native-google-speech-api)を試しました。
そろそろ組み合わせたものを作ろうかとも思ったのですが、その前に録音した音声を再生するところをやって見ようと思います。
さらにその前に、現状のApp.jsをちょっと変更したくなりました。

というのも、現状のソースは、
App.jsの下にChat.js(チャット制御)とSpeech.js(Google Speech to Text音声認識と録音制御)の2つのコンポーネントがぶら下がっている構成です。

----JSX:App.js-------------------------------------
:
import React, { Component } from 'react';
//import { SafeAreaView, View, Text, } from 'react-native';
import { Router, Scene, } from 'react-native-router-flux';

import Chat from './Chat';
import Speech from './Speech';

export default class App extends Component<{}> {
render() {
return (
<Router>
<Scene key='root'>
<Scene key='Text' component={Speech} title="Speech:Google音声認識" />
<Scene key='Chat' component={Chat} title="VTChat:チャットサンプル" />
</Scene>
</Router>
);
}
}
---------------------------------------------------

App.js内でreact-native-router-fluxを使って<Router><Scene key=’root><Scene ・・・/><Scene ・・・/></Scene>と2つ並べています。
2つの<Scene ・・・/>の切り替え方を知らないので、今のところ1番目の<Scene ・・・/>が動作を開始した後、切り替えは多分できないようになってます。

せっかくなので、音声認識(&録音)、新規:音声再生、チャットをそれぞれ切り替え可能にしたいと、ちょっと調べました。


◆<Tabs>を使って複数の機能をメニュー化する

「react-native-router-flux 切り替え」でぐぐって見ると、以下のサイトが引っ掛かりました。
参考:https://rara-world.com/react-native-tab-routing/
サンプルが載ってます。
しばらく、React Native JSXのコードから遠ざかっていたので、なんかサンプルコードに違和感が・・・

ともかく、react-native-router-fluxの<Tabs>というコンポーネントがあって、それを使って並べるようです。
結果の絵でもあれば、ちょっとイメージできていいんだろうけど、載ってません。

やってみた方が早いですね。

では、まずはコードです。
こんな風にしました。
----JSX:App.js-------------------------------------
/**
* Sample React Native App => Chat Sample
* https://github.com/facebook/react-native
*
* @format
* @flow
*/

import React, { Component } from 'react';
import { SafeAreaView, View, Text, StyleSheet } from 'react-native';
import { Router, Scene, Tabs } from 'react-native-router-flux';
import Icon from 'react-native-vector-icons/MaterialIcons';

import Chat from './Chat';
import Speech from './Speech';

const TabBarIcon = (props) => {
return (
<View style={styles.tabIconContainerStyle}>
<Icon
name={props.iconName}
color={props.focused ? 'blue' : 'grey'}
style={styles.tabIconStyle}
/>
</View>
);
}


export default class App extends Component<{}> {
render() {
return (
<Router>
<Tabs key='root' swipeEnabled={true} animationEnabled={true}>
<Scene key='Text'
component={Speech}
title="Speech:音声認識&録音"
iconName='mic'
iconColor='red'
icon={TabBarIcon}
initial
/>
<Scene key='Chat'
component={Chat}
title="Chat:チャット"
iconName='chat'
iconColor='red'
icon={TabBarIcon}
/>
</Tabs>

</Router>
);
}
}

const styles = StyleSheet.create({
tabIconContainerStyle: {
justifyContent: 'center',
alignems: 'center',
},
tabIconStyle: {
width: 24,
height: 24,
fontSize: 24,
},
});

---------------------------------------------------

どんなiconを使うのかは、「iconName」パラメタで指定しているようです。

「import Icon from 'react-native-vector-icons/MaterialIcons';」というのも初めて見るの書き方。
参考:https://qiita.com/kana-t/items/3cad4fae393b6a5fc8a0

react-native-vendor-iconsをインストールした後で分かったのですが、
react-native-vector-iconsに含まれる、アイコンのセット(.json)をimportしていることになるみたいです。

「(プロジェクトフォルダ)\node-modules\react-native-vector-icons\dist\glyphmaps」の下にMaterialIcons.jsonがあって、
中身を見ると、アイコン名らしき名前と番号がダーっと書かれてました。
その中から、「mic」と「chat」を選びました。

react-native-vendor-iconsのインストールは、いつもの通り、プロジェクトフォルダをカレントにして
npm install react-native-vector-icons --save
を実行しましす。

それで、「react-native run-android」を実行します。
すると、以下のような画面が出ました。
20200407_1.jpg

画面下部分に表示されているのがTabバーで、2つのメニューが表示されています。
起動時は、「音声認識&録音」側の機能が有効です。
各メニューをタップするとそれぞれの画面への切り替えが可能です。

ただし、アイコンは□に×のマークで、うまくアイコンが取り込めてないようです。

「rnpm link ・・・」もやれと書いてあるサイトがあった。
(↑注:iOS対応の場合であってrnpmです。npmではない。)
でも、「npm link ・・・」とやって、その後正常だったことは一度もない。
ちょっと躊躇してたのですが、やってみました。
(↓注:やってはいけません。)
npm link react-native-vector-icons

で結果は・・・

続きを読む



スマフォのアプリを作りたい(20):音声認識と同時に録音③

   プログラミング [2020/04/06]
前回の続きです。

録音込みの音声認識を作りました。
でも、なんだか録音処理を追加する前より認識率が悪くなったような気がします。
もぞもぞ話しても、ほとんど文字にしてくれません。
調子のいいときは、いいんだけど・・・。

録音してみて分かったのですが、PCのマイク入力を経由してAndroidエミュレータに渡ってくる音声の音質なんだかよくない。
ザラザラした感じの音で、プツプツした雑音も混ざってます。
それはそれで仕方ないことかもしれないけど、何とかならんのかな?

試しにサンプルレートを上げてみることにしました。

前回の記事に改造react-natove-google-speech-apiのAndroid向け修正ソースをまるっと乗せたので、コードの全容は前回記事をご参照ください。


◆サンプルレートを変えて見る
ベースの音声入力クラス(VoiceRecoder.java)でどうやってサンプルレートを決めているか見てみました。
以下のような配列が定義されています。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{16000, 11025, 22050, 44100};
それで、初期化時に以下のような処理関数を動かしています。
----VoiceRecoder.java------------------------------

private AudioRecord createAudioRecord() {
for (int sampleRate : SAMPLE_RATE_CANDIDATES) {
final int sizeInBytes = AudioRecord.getMinBufferSize(
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
);
if (sizeInBytes == AudioRecord.ERROR_BAD_VALUE) {
//Log.d(TAG, "invalid samplrate="+sampleRate);
continue;
}
//Log.d(TAG, "valid samplrate="+sampleRate);
final AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
sizeInBytes
);
if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
buffer = new byte[sizeInBytes];
return audioRecord;
} else {
audioRecord.release();
}
}
return null;
}

---------------------------------------------------

つまり、SAMPLE_RATE_CANDIDATES配列にセットされているサンプルレート毎にAudioRecordクラスをnewしてみて、そのステートが正常であればループを抜けています。
サンプリングレートの値は低目の値から並んでいるので、一番最初の16000でステートがOKならば、その値で確定してしまいます。
なんで、16000が先頭なんだ?
サンプルレートって高い方が「いい音」なのでは?
と思ったので、配列の順番を高い数値順に変えてみました。
private static final int[] SAMPLE_RATE_CANDIDATES = new int[]{44100, 22050, 16000, 11025};

結果から言うと、44100が選択されるけど認識率は変わりませんでした。

サンプルレートは、「音質」というものに直結するわけではない?

Google Cloudの説明に解説がありました。
参考:https://cloud.google.com/speech-to-text/docs/enccoding?hl=ja

高くすると「周波数の高い音を再現できるようになる」ということだそうで。
人間の耳で聞こえる周波数~20,000Hzを再現するのに必要なのが40000Hz以上(44100Hz)なのだそうだ。
さらに、その下の「非圧縮音声」のところを見ると、人の声として拾うなら16000Hzが適していると書いてます。

だからSAMPLE_RATE_CANDIDATES配列の先頭に16000があったのね。
よって、配列の初期化値の変更は不採用です。


◆見つけた不具合
上記の変更を試している最中に不具合を一つ見つけました。

音声入力時のサンプルレートを録音クラス(VoiceEncoder.java)に渡す処理(start()メソッド)のコール位置がよろしくありませんでした。
GoogleSpeechApiModuleクラスのstart()メソッド中にあったのですが、onServiceConnected()コールバックのVoiceRecorderクラスのstart()メソッドのコール後に移動しました。修正版のコード(GoogleSpeechApiModule.java)を全部載せます。

気になる方は、続きをご覧ください。

続きを読む



スマフォのアプリを作りたい(19):音声認識と同時に録音②

   プログラミング [2020/04/04]
前回の続きです。
「音声認識(react-google-speech-api)と同時にその音を録音させるには、ひとさまの作ったフレームワークを弄るしかない。」という結論に達しました。
しかし、ちょっとした修正ならまだしも、結構な作り込みになるのは予想つくので些か躊躇・・・というか、面倒臭くなってちょっとの間、現実逃避してました。
その後、シブシブ再開したが、Androidのことも、Javaについても全く無知なさるなので、やっぱりエライ時間が掛かりました。

録音処理の実装でトラブった話を纏まりなく以下に書きます。
初心者の方の・・・何かになるんでしょうか。


◆ああ、Javaだったのね
react-native-google-speech-api内にエンコード用の処理(ソースファイル/クラス)を追加する方針です。
ここで、上記のパッケージ内のコードが「.java」であることがジワジワ響いてきました。
JavaScriptすらド素人なのに、Javaは全く未経験です。
予備知識 0
なのに弄っちゃってるなんて無謀でしたよね。

JSとJAVAの違いも知らないのに、「違う言語だ」という認識も薄いため、コードをどう書けばいいのか行き詰ることもしばしばでした。
元々のコードも理解できてないのに、それらの書き方を適当に真似してみるというやり方です。

まずは初期のころ、
・追加したエンコード・クラス内のメソッドに、意識せずに「static」指定してしまったり
・呼び出し元でクラスのインスタンス生成(new)の要/不要やタイミングとか分かってなかったり
イミフなビルドエラーが出まくりました。

ちょっと分かった気分になれたのは以下の解説のおかげ。
参考:https://java.keicode.com/lang/initialize-initialization-block.php
(他サイトは細かい説明も含まれていて耳からミソが垂れてきそうでした。)
さる並みの方は上記のサイトを頭から読んでお勉強されることをお勧めします。
 さる自身は・・・まあイズレね。

ちょっと知恵がついたことと言えば、
  • メンバ変数の初期化は、コンストラクタ(クラス名のメソッド)を書かなくてもできるらしい。
  • 単にクラス内に変数を定義して、「・・・= xxx;」とかやっとけば、そのクラスのオブジェクト(インスタンス)が生成(new)されたときに初期化されるらしい。
  • 固定値で初期化するのであれば、「static」と付ける。これを「クラス変数」とか呼ぶ。これに対して先の「new」時に初期化されるのを「インスタンス変数」と呼ぶ。
  • 「static」を付けたメソッド/メンバは、「new」しなくても呼び出し/参照できる。クラス名.メソッド名()/クラス名.変数名 と記述して使う。
  • 以上から察するに、コンストラクタ(クラス名と同じ名前のメソッド)を明示的に定義する意義は、
     -規定クラスの初期化を引き継げる(super()する)ことや、
     -メンバ変数をコンストラクタ「new クラス名(引数)」時に初期化内容を引数で制御できること
     かと思う。
  • でもイミフな現象がありました:
     -例えば、「AruClass」という名前でクラスを定義して、
     -参照側クラスのメンバ変数を「AruClass aruClass = new AruClass();」とやって、
     -参照側クラス内のメソッドから「aruClass.xxxxx();」とやったら、
     -エミュレータで実行しかけた時に「xxxxx()はstaticじゃねーよ!」的なエラーになった。
     →クラス名とは頭1文字違う「aruClass」としてるんだけど・・・
      「AruClass aruCla = new AruClass();・・・aruCla.xxxxx();」的な修正をしたら治まった。


◆Context(ApplicationContext)の参照の仕方が分かりません
Androidの本家の説明では、「Context」とか「Application」とかのクラスが準備されていて、これらを使うと、アプリケーション毎に固有に割り当てられたリソースに関する情報を参照できるように書かれてありました。

アプリ毎にワークのディレクトリ(ストレージ上のフォルダ)も準備されているらしい。
それをエンコードしたファイルの出力先にしようとして、追加したエンコード処理クラスの中で「Application myapp = new Application();」とかやったのですが、どうも上手くいきません。
「myapp.getFilesDir()」でExceptionになります。「Contextがnull」だとメッセージが出ます。Applicationクラスの基底クラスがContextなのは分かるけど、myappはnullではないのは確認しました。
正体が掴めず、この件は挫折。
(呼び出しの元(JavaScript側)でファイル名パスを指定する方向に変更しました。


まだ、序の口です。ぼやきは続きます・・・

続きを読む



スマフォのアプリを作りたい(18):音声認識と同時に録音

   プログラミング [2020/04/02]
だいぶ間が空いちゃいましたが、ハマりまくってたためです。
ここ数か月掛けてもなお、思ってたような成果が出せてません。
さるだから、仕方ない。
春っぽくなって、野外の活動を始めたので、こっちに割ける時間が減ったのもある。

巷は新型コロナで大変な状況のようですが、そろそろ圏内でも染った話が頻繁になってきた。
ヤバイかな。さるもリスクの高い年齢だし、タバコ吸いまくってるし、染りたくないなぁ。

ともかく、「スマフォのアプリを作りたい」続けます。

音声認識させてみたんだけど、結局、100%の音声認識(テキスト化)は不可能なのは、凡そ見当がついてました。
どうも、話す内容がちゃんとした「文章」になってないとあまり正確な認識はしないらしい。
頭の中で「文章」を組み立ててから話始める人なんかそうそういない。
それに、話す側の発音(訛り)の問題とか、周囲の雑音が思いのほか影響するみたいです。
一度、空調送風音の大き目の場所でタブレットの内蔵マイクで試してみたら、ほとんどまともに変換してくれませんでした。

そんな場合、認識させた音声そのものを録音しておいたら、相手、あるいは本人が聴いたときは、判別できるんではないだろうか。
この分野は、未だ人間様の言語認識能力の方が高いはず。

というわけで、
音声認識はさせておくんだけど、同時に録音(ファイル化)がしたいってことです。


◆フレームワークに何を使うか
ちょっと、React Nativeの事例をみると、録音(ファイル化)してみたという記事はたくさん見つかる。
素直に、そのパッケージを使ってやればいいのかな。

でも、react-native-google-speech-apiのコードを見てた時、音声データが定期的に送られてくる箇所があった。
そのデータをGoogle Cloudに送り込んでるんだけど、それと同時にファイルに突っ込めないのだろうか。
効率よさそう。
とは、思ったものの・・・・

そういうレベルで制御しているサンプルは見つけられず、

react-native-google-speech-apiパッケージ内で使っていた「MediaRecorder」というAndroidのマルチメディアフレームワークの使い方を検索してみました。
参考:https://developer.android.com/guide/topics/media/mediarecorder?hl=ja
録音にも使えそうです。
でも、
・バッファによる入力部とファイル保存部のデータ受け渡しの処理は見られません。
・Android固有の処理ということになります。iOSのときには、同等の別の処理が必要ということになります。
 (なので、置き場所や「切り替え方」も意識しないといけなくなります。)
※そういえば。導入してみたreact-native-google-speech-apiの仕様が気に入らなくて修正しちゃいました(前々回の記事)が、iOS側もいずれ何とかしないといけないんですね。

ちょっと悩んだけど、面倒だなと思って、結局react-native-audioを使うサンプルをマネしてみることに。
参考:https://blog.leko.jp/post/rn-audio-record/


◆react-native-audioのインストール

1)「npm install react-native-audio --save」
react-native-google-speech-apiで四苦八苦したことが記憶に新しいので、少し不安もありましたが、やってみました。

----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d d:\appmake\proj\vtchat

d:\AppMake\proj\VTChat>npm install react-native-audio --save
npm WARN @typescript-eslint/eslint-plugin@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/parser@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.



+ react-native-audio@4.3.0
added 1 package from 1 contributor and audited 957442 packages in 67.884s

21 packages are looking for funding
run `npm fund` for details

found 19 vulnerabilities (4 low, 15 moderate)
run `npm audit fix` to fix them, or `npm audit` for details

・────────────────────────────────・
│ │
│ New minor version of npm available! 6.12.1 -> 6.14.2 │
│ Changelog: https://github.com/npm/cli/releases/tag/v6.14.2 │
│ Run npm install -g npm to update! │
│ │
・────────────────────────────────・
---------------------------------------------------

余計なnpmの宣伝も出たけど、成功した模様。

2)「react-native link react-native-audio」(不要かも)
参考サイトではやるとあるのですが、
さるの環境ではやらなくてよかったコマンドのようです。

とりあえず、「react-native link・・・」すると以下のメッセージ。
----コマンドプロンプト-----------------------------
d:\AppMake\proj\VTChat>react-native link react-native-audio
info Linking "react-native-audio" iOS dependency
info iOS module "react-native-audio" has been successfully linked
info Linking "react-native-audio" Android dependency
info Android module "react-native-audio" has been successfully linked
---------------------------------------------------

これも何事もなく終わってくれるんですが、「react-native run-android」したら、
----コマンドプロンプト-----------------------------

error React Native CLI uses autolinking for native dependencies, but the following modules are linked manually:
- react-native-audio (to unlink run: "react-native unlink react-native-audio")
This is likely happening when upgrading React Native from below 0.60 to 0.60 or above. Going forward, you can unlink this dependency via "react-native unlink " and it will be included in your app automatically. If a library isn't compatible with autolinking, disregard this message and notify the library maintainers.
Read more about autolinking: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md

---------------------------------------------------

てなエラーになります。
なので、結局「react-native unlink・・・」しました。
----コマンドプロンプト-----------------------------
d:\AppMake\proj\VTChat>react-native unlink react-native-audio
info Unlinking "react-native-audio" iOS dependency
info iOS module "react-native-audio" has been successfully unlinked
info Unlinking "react-native-audio" Android dependency
info Android module "react-native-audio" has been successfully unlinked
---------------------------------------------------


3)「android/app/src/main/AndroidManifest.xml」修正
これもまた、さる環境ではreact-native-google-speeck-apiのときにやってたので済み。


◆録音処理の味見
先に挙げたサイトの説明を参考に実装してみました。
ところが、以下の実装(一部抜粋)だとthis.record()=>AudioRecorder.startRecording()でExceptionが発生しました。
----Speech.js--------------------------------------

const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
{
title: 'Record Audio Permission',
message:
'App needs access to your microphone ' +
'so you can convert speech to text.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('permission granted');
this.startListening();
await this.setUp();
await this.record();

} else {
console.log('permission denied');
}

---------------------------------------------------

そこで、録音関連の処理とstartListening()と順番を変えてみたところ、Exceptionは発生しなくなった。
----Speech.js--------------------------------------


if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('permission granted');
await this.setUp();
await this.record();

this.startListening();
} else {
console.log('permission denied');
}

---------------------------------------------------

録音はされたようだけど、音声認識はされません。

録音された音声ファイルは、以下のコマンドで取り出せました。
----コマンドプロンプト-----------------------------
d:\AppMake\Android\Sdk\platform-tools>adb pull /data/user/0/com.vtchat/filesvoice.aac C:\temp\
/data/user/0/com.vtchat/filesvoice.aac: 1 file pulled. 3.1 MB/s (187558 bytes in 0.057s)
---------------------------------------------------

参考:https://qiita.com/t2low/items/cb37cec5f864c4748e14
※ソース上で、「AudioUtils.DocumentDirectoryPath」とされているのが「/data/user/0/com.vtchat/files」になっているのをデバッガで確認。

取り出したファイルを再生しても見ました。音質は良くありませんでしたが、確かにしゃべったことが録音されてました。

GoogleSpeechApiのlogcat(Log.i())メッセージによると、どうも音声データがGoogleSpeechApi側に渡ってこなくなっているみたいです。
さもありなんな現象です。

単にマイク入力をファイル化するだけなら、最初の方で上げた参考サイト(https://blog.leko.jp/post/rn-audio-record/)のやり方でOKということです。

でも今回、そうではないので、もう一回調べ直し・・・・

続きを読む



スマフォのアプリを作りたい(17):音声認識させたい⑤

   プログラミング [2020/03/10]
えーと。
React Native環境で、クロスプラットフォームなアプリを作ろうとしています。
最初、チャットアプリの基本をやってみて、
前回までに、音声認識(音声→テキスト変換)を試作してみました。

作ったアプリはGoogle Cloudを利用するものです。
ただし、音声認識させてはみるものの、
(1)変換がスムーズに続かない。
(2)認識精度がいまいち。

これは、入力している音声データに問題があるのかも。

今回は、テスト環境/音の入力についてのさるの迷走ぶりを書きます。


◆動作確認環境/ヘッドセット(マイク)について
さるの開発(試験)環境は、Windows10タブレットPCで、Androidエミュレータ上でアプリを起動して動作を確認しています。

未だに、実際のスマフォでテストしたことはありません。
それはなぜか

・Androidスマフォ(SIMフリー)の中古版をアプリ開発前に勇んで買いました。
新品 未使用 ARROWS Me F-11D Precious Black docomo スマホ 白ロム 本体 送料無料【当社6ヶ月保証】【中古】
価格:5,980円・・・ただし、ポイント使ったので実際は2000円くらい。

が、このスマフォのAndroidのバージョンが4.0なのに対して、当初想定の開発環境(VisualStudio)が未サポートだった。
React Native(Android Studio)に開発環境を切り替えたが、Androidエミュレータのminimumバージョンが6.0だった。
ってことは、エミュレータで動作確認しても実機で動く可能性が低い。

一方、音声入力についてはもっと迷走した。
・内蔵のマイクは、ハズイ。
電車の中とか外で電話しちゃっている人とか、声が大きくなって、周りに丸聴こえのことが多いですよね。
何か、文章を入力するとか、メッセージをテキストにして伝えたい場合、スマフォ/PCに向かって大き目の声で一人ぶつぶつ言うのはちょっとねぇ。

・ヘッドセット(USB1.0)を既に持っていたのですが・・・
WindowsタプレットPCにUSB-TypeAの口が一個しかなく、その口を増設HDD(SSD)に使っちゃってるので塞がってます。
HUBを使えばいいんですけどね・・・。いずれ、外で手軽に使える感じではないですね。

・ともかく、線で繋がなくてもよくて小さいものを買いました。
無線カケトーク ブラック Bluetooth ヘッドセット 通話 片耳 高音質 耳掛け型 ワイヤレス マイク内蔵 スポーツ KAKETALK-BK
価格:1,080円

が、タブレットにBluetooth接続してみたら、ぶつぶつ話す声はほとんど入りませんでした。サウンドコントロールパネルでレベルメーターみたいなのがあるのですが、ほとんど拾ってないのが分かります。
20200310_1.jpg

買い物に失敗しましたが、まだ諦めが付きません。

続きを読む



スマフォのアプリを作りたい(16):音声認識させたい④

   プログラミング [2020/03/07]
前回、react-native-google-speech-apiパッケージを使って、何やら日本語の音声認識動作ができるところまで確認しました。
ただし、続けて動作させているうちに、ハング状態になる問題があります。
それと、使用言語を日本語にはしてみましたが、パッケージ自体はあまり汎用的な作りになっていない感じです。
上記をもうちょっと改善したいなーなんてちょっと無謀かもしれませんが、やってみようかと・・・。

まずは、Exampleのコードが何をやってそうか予想するところからになります。

◆react-native-google-speech-apiのApp.jsの概要
react-native-google-speech-api\ExampleAppにあったApp.jsについてです。
さるが使っているプロジェクト内では、Speech.jsという名前のファイルにして、処理はSpeechクラスとして定義しています。
実際のコードの内容に関しては、前回の記事に丸っと載せたのでそちらをご参照ください。(根拠のない無責処理が含まれます。)

まずは、初期処理:componentDidMount()メソッドで、
・GoogleSpeechApi.setApiKey()メソッドで、Google Cloud Platformの「APIキー」を設定しています。
・EventEmitter.addListener()で、「onSpeechRecognized」と「onSpeechRecognizedError」と命名されているイベントに対してコールバック処理を定義しています。

実際の操作に関しては、render()メソッドで、
・「Start listening」と表示された(なぜか、キャプションとしてはすべて大文字で表示される。)ボタンをタップした場合、requestAudioPermission()メソッドがコールバックされるように指定しています。
・requestAudioPermission()メソッドでは、「async」※1と入っているため非同期実行なのかと思います。PermissionsAndroid.request()メソッドの実行完了を待って、自startListening()メソッドを呼び出しています。予想ですが、PermissionsAndroid.request()は、マイク入力の使用の許可申請を行うメソッドかと思います。
・startListening()メソッドでは、ボタンのキャプションを「I'm listening」に変更したのち、GoogleSpeechApi.start()メソッドを呼び出しています。予想ですが、この時点でマイク入力音声をGoogleCloud側に送り込み認識(テキスト変換)することを開始指示しているかと思います。

マイクの入力があった場合は、
・componentDidMount()メソッド内のEventEmitter.addListener()で指定した2つのfunctionが「onSpeechRecognized」と「onSpeechRecognizedError」の2種類のイベントに応じて実行されるものと思います。


いくつか分からないことがあります。

・startListening()した後で発生するイベントは、「onSpeechRecognized」と「onSpeechRecognizedError」だけ?
・もし、マイクから音が入ってこない場合は、永遠に待つ?タイムアウトはないのか?
・上記の「待ち」を強制的に終了させることはできないのか?
・同じく「待ち」状態のタイミングで、ボタンを再度タップした場合、requestAudioPermission()を再度実行してしまう。ガードしている節がない。大丈夫なのか?交通整理(待ち)とかキューインとかの能力がPermissionsAndroid.request()、あるいはGoogleSpeechApi.start()メソッド内にあるのか?

上記、辺りがハングする原因とその際のステート不明の原因ではないかと考えます。


-※1:ちょっと寄り道:asyncとawait-
いきなり、そんなこと言われても・・・JavaScriptド素人なので分かりません。
以下を読み始めました。
参考:https://qiita.com/soarflat/items/1a9613e023200bbebcb3
が、いきなり「Promise」を理解していることが前提で書いているみたいなので、(それすら知らないさるは)以下を読んでみました。
参考:https://qiita.com/toshihirock/items/e49b66f8685a8510bd76
※いずれもややこしい話をしていて、誤解があるといけないので、以下のさるな要約は信用しないで、ご自分で理解されることをお勧めします。

上記参考サイトのサンプルのコードの中にsetTimeout()という関数がよく出てきます。そこの理解からです。
「id = setTimeout(処理、実行タイミング);」と書くと、「実行タイミング」後に、「処理」を実行するという処理です。setTimeout()は、コールされた直後にid(タイマーのID)をリターンして次のステートメント(処理)を実行できるようになります。「実行タイミング」はmSec単位で指定します。例えば、「実行タイミング」が十分長く、直後に「clearTimeout(id);」とかやると、「処理」は実行されないでしょう。

new Promise((resolve, reject) => {処理});」とやると、Promise型(どこにも、Promiseがクラスだとか、Function型だとかの説明記述は見られませんでしたが、その方が理解しやすいかと思ってそう書きます。)「処理」=非同期実行される「処理」を定義/生成することを意味します。
function asyncFunc1(param) {return new Promise((resolve, reject) => {処理});}」とやれば、asyncFunc1は非同期で「処理」を実行する関数を定義したことになります。
「resolve」と「reject」はそれぞれ処理完了時のコールバック関数を2種類指定できるようになっていて、「resolve」は正常時、「reject」は異常時という約束になっているみたいです。「resolve」「reject」をどう使うのかは、「処理」の中身:Promise関数の作り手の自由になっています。
実行では、「asyncFunc1(param1).then(resolve関数、reject関数).catch(例外処理関数);」という記述の仕方になります。resolveでもrejectでもない結果の場合には、.catch()で指定された関数が実行されるということになります。reject関数指定は、省略される場合が多いみたい。「asyncFunc1(param1).then(・・・).catch(・・・);」は終わりを待たずに次のステートメントが実行されるものと思われます。「resolve関数」、「reject関数」指定を省略した場合、Promise関数内で使っていないのであれば何もしないと思いますが、使っていてコールバック条件が成立した場合は、例外が発生するかと思います。「catch.(例外処理関数)」が省略された場合は例外が発生しても何もしないということになります。※.finally()もES9でサポートされたそうです。蛇足でした。

さて、「async function asynFunc2() {・・・}」は、「function asyncFunc1(param) {return new Promise((resolve, reject) => {処理});}」と同じ働きのようです。一方、「const result2 = await asyncFunc2();」とやった場合には、asyncFunc2()の完了を待って、結果をresult2に入れるという意味になります。非同期じゃなくなります。ただし、「await」はasync関数の中でしか使えないという制限があります。んー、非同期関数内から非同期関数を呼ぶ場合に使うということですね。※ちなみに「asyncFunc2();」とやった場合、.then()とか.catch()を指定していないので、「非同期の結果如何による処理分けはしない」という場合ですね。



さらに、react-native-google-speech-apiパッケージ内のスクリプトを斜め読みします。

続きを読む



スマフォのアプリを作りたい(15):音声認識させたい③

   プログラミング [2020/02/27]
react-native-google-speech-apiというパッケージを見つけて
糠喜びしたのもつかの間
ドはまりした話を前回書きました。

やっと、やっとGoogleのSpeech-to-Textを追っかけます。

さて、今回はサンプルコードを追っかけて、実際の音声認識をやってみて、その精度を確認したいと(今時点では)思っています。

◆react-native-google-speech-apiのサンプル
まずは、react-native-google-speech-apiのサイトにあったサンプルコードはちょっと処理が少なかったので、インストールした同パッケージ・フォルダ内のExample\App.jsを参考(丸写し+α)して、Speech.jsを作り直しました。
----Speech.js--------------------------------------
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/

import {
NativeModules,
Platform,
NativeEventEmitter,
DeviceEventEmitter,
Text,
View,
Button,
Alert,
PermissionsAndroid,
} from 'react-native';

import React, { Component } from 'react';

const { GoogleSpeechApi } = NativeModules;

const EventEmitter = Platform.select({
android: DeviceEventEmitter,
ios: new NativeEventEmitter(GoogleSpeechApi),
});

export default class Speech extends Component {

constructor(props) {
super(props);
this.state = {
currentText: "",
previousTexts: "",
button: "Start listening"
};
}

componentDidMount(){
GoogleSpeechApi.setApiKey("Your google access token");
EventEmitter.addListener('onSpeechRecognized', (event) => {
var previousTexts = this.state.previousTexts;
var currentText = event['text'];
var button = "I'm listening";
if (event['isFinal']){
currentText = "";
previousTexts = event['text'] + "\n" + previousTexts;
button = "Start listening";
}

this.setState({
currentText: currentText,
previousTexts: previousTexts,
button: button
});
});

EventEmitter.addListener('onSpeechRecognizedError', (error) => {
this.setState({
button: "Start listening"
});
Alert.alert(
"Error occured",
error['message']
);
});

EventEmitter.addListener('onSpeechEnd', (event) => {
console.log('Speech end');
});
EventEmitter.addListener('onSpeechError', (event) => {
console.log('Speech error');
});
EventEmitter.addListener('onSpeechResults', (event) => {
console.log('Speech Results');
});

}


startListening = () => {
this.setState({
button: "I'm listening"
});
GoogleSpeechApi.start();
}

requestAudioPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
{
title: 'Record Audio Permission',
message:
'App needs access to your microphone ' +
'so you can convert speech to text.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('permission granted');
this.startListening();
} else {
console.log('permission denied');
}
} catch (err) {
console.warn(err);
}
}

render() {
return (
<View style={{ margin: 30 }}>
<Text>{this.state.currentText}</Text>
<Text>{this.state.previousTexts}</Text>
<Button
title={this.state.button}
onPress={Platform.OS === 'ios' ? this.startListening : this.requestAudioPermission}/>
</View>
);
}
}
---------------------------------------------------

※サンプルコードから以下を修正しています。
1)サンプルコードではところどころ「;」が無いところがありました。でもBuildは通りました。でも、なんだか気持ちが悪いので、「;」を追加しています。
2)それと、EventEmitter.addListener()メソッドで、イベント発生時のコールバック関数を指定できるようなのですが、デバッグ用に少し追加しました。ただし、イベント名はreact-native-voiceで使っているものを当てずっぽうで持ってきてます。


さらっと見た感じで、
1)Googleアクセス・トークンというのを指定しないといけないみたいです。
2)使用言語を指定している部分が見当たりません。
まずは、上記2点について調べます。




◆Google Cloud Platformの認証情報について
参考:https://cloud.google.com/speech-to-text/docs/reference/libraries
上記のサイトの途中に「[サービスアカウントキーの作成]ページに移動」というリンクがあります。
それをクリックして、表示される画面で「新しいサービスアカウント」/アカウント名/「Project」-「オーナー」/「JSON」を指定して、[作成]ボタンをクリックします。
以降、図の表示が小さくて見えない場合は、クリックすると文字が見える程度の画像で表示すると思います。
20200227_1.jpg

「My First Project-xxxxxxxxxxxx.json」というファイルがダウンロードされます。
中身は、以下の感じ。
どれくらい秘匿性のあるものなのか分からないので、だいぶ省略(・・・・)しちゃってます。
----JSON:------------------------------------------
{
"type": "service_account",
"project_id": "・・・・",
"private_key_id": "・・・・",
"private_key": "-----BEGIN PRIVATE KEY-----\n・・・・\n-----END PRIVATE KEY-----\n",
"client_email": "・・・・",
"client_id": "・・・・",
"auth_uri": "https://・・・・",
"token_uri": "https://・・・・",
"auth_provider_x509_cert_url": "https://・・・・",
"client_x509_cert_url": "https://・・・・"
}
---------------------------------------------------

どれが、トークン? JSON自体がそれ?
指定先のメソッドがGoogleSpeechApi.setApiKey()なので、「APIキー」?を指定するのか?

JSONをダウンロードした後に表示されたブラウザ上ページには、確かに「APIキー」という記述も見えて、先ほどのアカウント(.json)とは別に確保もできるっぽい。

Googleさんの認証に関する説明がありました。
参考:https://cloud.google.com/docs/authentication
ふぇーん。何言ってるのか分かんない。

続きを読む



スマフォのアプリを作りたい(14):音声認識させたい②

   プログラミング [2020/02/20]
前回は、
・Google Cloud Speech to Textの利用者登録をして、
・Androidエミュレータのマイク入力設定をやり、
・react-native-google-speech-apiの嘘くさいインストールをやって、
・勢い余ってreact-native-google-speechもインストールし、
・音声認識のサンプルコードをプロジェクトに取り込んだ
ところまででした。

その続きをやってみたときのメモです。
カオスというかパニックというか・・・
ともかく、ひっちゃかめっちゃかです。

なので、この回は初心な方には読む価値なしです。

さるはバカなので、やっていることのほとんどは闇雲です。
なので、すぐトラブルになります。
失敗して、やり直し、手戻り続きです。

本当は、そこを省いて成功手順だけ書けば親切なんでしょうが、自分のための備忘録なので、全部載せます。
同じエラー(メッセージ)に遭遇した時とかに何かの足しに・・・なるのかなぁ。


今回、
・react-native-google-speechを含んだ環境で発生した各エラーについて
 →◆サンプルのビルド(react-native-google-speech有り)

・react-native-google-speech-apiのnpm installでENOVERSIONSの発生の対策
 →◆react-native-google-speech-apiのインストールし直し

・react-native-google-speech-api追加後のビルド失敗から環境破壊
 →◆サンプルのビルドからパニック

・プロジェクトの再構築からビルドが通るようになるまで
 →◆環境を作り直し~react-native-google-speech-apiビルド

最後だけが、「もしかしたら参考になるかも」です。


◆サンプルのビルド(react-native-google-speech有り)
果たして動くんでしょうか。
「react-native run-android」を実行し、ビルドを行って見ます。

当然、すんなりとはビルドは通りませんでした。

最初にreact-native-google-speech-apiの「手動インストール」の入力ミスでエラーが出ました。
そこからです。

1回目:Unable to delete directory
----コマンドプロンプト-----------------------------

What went wrong:
Execution failed for task ':react-native-google-speech:generateDebugBuildConfig'.
> java.io.IOException: Unable to delete directory (プロジェクトフォルダ)\node_modules\react-native-google-speech\android\build\generated\source\buildConfig\debug\com\prayagad.

---------------------------------------------------
→この前の実行で、フォルダが中途半端に作成されたままになったみたいです。
「・・・buildConfig\debug・・・」のdebug以下を一旦削除して、「react-native-google-speech」フォルダへのアクセス権がなぜか制限されてたので、フルアクセスに変更してあげました。

2回目:Annotation processors must be explicitly declared now.
----コマンドプロンプト-----------------------------

> Task :react-native-google-speech:javaPreCompileDebug FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.5/userguide/command_line_interface.html#sec:command_line_warnings
27 actionable tasks: 6 executed, 21 up-to-date

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native-google-speech:javaPreCompileDebug'.
> Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration.
- auto-value-1.1.jar (com.google.auto.value:auto-value:1.1)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

---------------------------------------------------
→上記のメッセージ後にもう一回別の「FAILURE:」が表示されているが、「What went wrong:」の内容が同一なので、割愛する。

どうも『Gradle 6.0としては、よくない機能が使われた』と言ってるような・・・

またもや、新単語。Gradleって何よ!
一言で言えば「ビルドシステム」だそうです。つまり、ビルドの手順をJVM上で動くスクリプト(Groovyと呼ばれる。)で書けるとあります。
はぁ・・・そっそうなんですか・・・

で、その後のメッセージは『やろうとした「react-native-google-speech:javaPreCompileDebug」というのが失敗しちまったぜ。何が悪かったって、annotationProcessorは今でははっきり指定しないといけないってことよ。compile classpathで指定されているdependenciesがannotation processorを含んでいるから、以下の指定を追加してみろよ。別の方法もあるっちゃぁあるんだが・・・』って言ってるのかなぁ。
全く・・・訳してみても意味が理解できません。
何言ってんの?どこのファイルのこと?

どうも「annotationProcessor」指定というのは、(プロジェクトフォルダ)\node_modules\(パッケージフォルダ)\android\build.gradleで指定するものらしい。
あちこち見て回って、理解はしてないけど、以下のように指定を突っ込んだ。
----build.gradle-----------------------------------
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')


// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.8.5'

// added for Gradle error comment
annotationProcessor "com.google.auto.value:auto-value:1.1"


---------------------------------------------------



まだまだ、この調子で続きます。

続きを読む



スマフォのアプリを作りたい(13):音声認識させたい

   プログラミング [2020/02/14]
「スマフォのアプリを作りたい」も13回目になりました。
これまでのこのタイトルの記事の流れは、こんなんなってます。
Start
 →スマフォのアプリを作りたい
  →開発環境をVisualStudioで・・・挫折
  →開発環境をReact Nativeで
   →環境構築続き(失敗)リトライ
   →デバッガの動かし方
  →React Nativeのソースの書き方
   →ReactのJavaScriptの概要
   →React Nativeのテンプレートを読む
  →簡単なチャットアプリを作る
   →サンプル味見ちょと修正
   →音声入力とエミュレータ操作
   →サーバ側動作環境の準備
   →アプリとサーバでチャット
  →音声認識をやってみる
←今回はココ

音声認識をやってみたいなーなんて思ってます。
かと言って、音声認識エンジンを作るとかいうことではなく、アプリから利用できればいいんです。
しかも、ソフトキーボードのマイクアイコンとかではなく、アプリから直接的に開始-終了とか制御できるようにしたい。

以前、エミュレータ(AVD)既設の機能を試したときには、音声の入力すら確認できなかったので、いまのさる環境で作って/試せるかは、かなり不安があります。


◆Google Chromeの音声認識
さるの今のレベル(ど素人)からすると、かなりハードルが高そうなことをやろうとしていると自覚しているので、気分を高めるために、以下のサンプルをご紹介します。

Chrome上でしか機能しないと思いますが、Googleさんの音声認識が簡単に使えちゃうHTML(JavaScript)です。
ほぼ、どっか(だいぶ前に作ってあったのでどこだったか忘れちゃいました。ごめんなさい。)のパクリをイジイジしたものです。

----HTML:-----------------------------------------
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>音声合成・認識アプリ</title>
</head>
<body>
<input id="txt1" type="text" value="おめのガバン、おぼでぐねが?">
<input id="btn1" type="button" value="話す">
<script>
var btn1 = document.getElementById("btn1"); //ボタンの取得
btn1.addEventListener("click", function() { //ボタンがクリックされたら
var synth = new SpeechSynthesisUtterance(); //設定を入れるオブジェクト
var txt1 = document.getElementById("txt1"); //テキストボックスを取得
synth.text = txt1.value; //話す内容
synth.lang = "ja-JP"; //言語
synth.rate = 1.0; //速さ
synth.pitch = 1.0; //高さ
synth.volume = 1.0; //音量
window.speechSynthesis.speak(synth); //話す
});
</script>
<br>
<br>
<input id="btn2" type="button" value="認識開始">
<div id="txt2">開始待ち</div>
<br>
<div id="txt3">ここに音声認識結果を表示</div>
<script>
var recog = new webkitSpeechRecognition(); // 音声認識オブジェクト
var fstart = false;
var btn2 = document.getElementById("btn2");
var txt2 = document.getElementById("txt2");
var txt3 = document.getElementById("txt3");
// ボタンを押した時の処理
btn2.addEventListener("click", function() {
fstart = !fstart;
if(fstart) {
txt3.innerHTML = "";
btn2.value = "認識停止";
recog.lang = "ja-JP"; // 認識する言語の設定
recog.start(); // 音声認識をスタート
}
//alert("sutate:"+fstart);
});
// 認識開始した時
recog.addEventListener("soundstart", function() {
txt2.innerHTML = "認識中...";
});
// 認識終了した時
recog.addEventListener("end", function() {
if(fstart) {
recog.lang = "ja-JP"; // 認識する言語の設定
recog.start(); // 音声認識をリスタート
}
else {
btn2.value = "認識開始";
txt2.innerHTML = "開始待ち";
}
});
// 認識が成功した時
recog.addEventListener("result", function(ret) {
txt3.innerHTML += "<br>" + ret.results[0][0].transcript;
});
// 認識に失敗した時
recog.addEventListener("nomatch", function() {
txt2.innerHTML = "認識できませんでした";
});
</script>
</body>
</html>
---------------------------------------------------


ためしに、以下に置いてみました。よかったら試してみてください。
https://sarumosunaru2.000webhostapp.com/voicebychrome2.html
[認識開始]ボタンを押してからマイクに向かって何か話せば、話した内容がテキスト化されて表示されます。

マイクの感度がよくて、発音がしっかりしていれば(訛ってなければ)かなり認識してくれます。
すげーと思います。
ただし、PC版のChromeでしか動かないみたいです。スマフォ(iPhone)のChromeでは反応しませんでした。
当然、Androidエミュレータ上の「ブラウザ」でも動きませんでした。

マイクが有効かどうかは、以下の手順で確認できます。(Windows10)
-タスクバー上の入力欄に「サウンドの設定」と入力して、リスト表示される一番上の「サウンドの設定」を選択します。
-右側の内容をスクロールして、「サウンドコントロールパネル」をクリックします。
-[サウンド]ダイアログが表示されるので、[録音]タブを選択します。
-使用可能な(チェックマーク付き)マイクが存在するかを確認してください。
-あれば、そのマイクの右側のインジケータが、音に反応して動くかを確認してください。
有効なマイクが無い、あるいはインジケータが動かないなどの場合は・・・
色々と原因があることなので、ご自分でなんとかしてください。

キーボード入力が苦手なのに、何か「文章をパソコンに入力しないといけない」なんて言う方は、先のページを使って、
-文章にしたい内容を話して→テキストに変換する
-画面に表示されたテキストをコピペしてどっかにコピーする
って使えば、結構な効率アップになるかもよ。


では、そろそろ本題についての調べて/試す独り言を続けます。

続きを読む



スマフォのアプリを作りたい(12):React Nativeでチャットアプリ味見⑤

   プログラミング [2020/02/07]
いつ、このサブタイトル「React Nativeでチャットアプリ味見」から離れられるか、ちょっと想像付かなくなってきてます。
ちょいちょいっと簡単なものなら作れるかと思って始めましたが、そうも行ってません。
深いです・・・っていうか、やたら色んなモノが関係してきて、分けがわかんなくなりそうです。
調べを続けて行く内に、前のコトの意味を忘れていきます。年ですな。

「スマフォのアプリを作りたい」で始めたこの話の状況はこんなんなってます。
Start
 →スマフォのアプリを作りたい
  →スマフォ側の環境はReact Nativeを使用します
   →試しにチャットアプリでReact Nativeコードを味見して見ます
    →スマフォ側のUIをサンプル・コードで動かしてみました
     (react-native-gifted-chatを使ったサンプル)
    →サーバ側動作環境を準備した
     (RatChetを使ったサンプル)
    →スマフォとサーバでチャット動作を試したい
←今回はココ

と、ここで・・・「前のスマフォ側コードにチャットサーバを設定しているようなところを見かけた気がしない。Sendとかやってたっけ?」「react-native-gifted-chat」はUI-ONLYなのかしら?
まずは、そこから調べはじめます。

「スマフォのアプリを作りたい(8)・・・」辺りから読んでいないと、以下の内容は読んでも理解いただけないかと思います。特に前提となるチャットサーバ環境/準備手順等については、前回記事をご参照ください。


◆Gifred-Chatは通信処理を含むのか?
以下を読むと、どうも含んでいないらしい。
参考:https://qiita.com/Satoooon/items/b3d781f1caafe394f134

でもって、「react native websocket」で検索すると・・・
React NativeでWebsocketを使うフレームワークがあるらしい。
参考:https://github.com/tiaanduplessis/react-native-websocket
でも、その中身と使用例を見ると、なんだか違和感がある。
WSというコンポーネントが定義されていて、それを使うようになっているみたいだが、
GiftedChatコンポーネントの中のメソッドからどうやってそれらを使うのかちょっとイメージできない。

さらに、検索して以下のページが出てくる。
React Native本家:https://facebook.github.io/react-native/docs/network
上記の「WebSocket Support」の部分の説明で概要は分かった気になれたが、react-native-websocketの利用例とはまったく別ものです。
はい。ここで勘違いしてはいけないのが、本家の説明はWebSocketの基本的な使い方であって、react-native-websocketのことではないということです。

さらに、「React Native Cookbook 著者:Stan Bershadskiy, Crysfel Villa」という市販本の一部をGoogleブックスから見ることができました。P213辺りでWebSocketの使い方が説明されています。URLはクソ長かったので省略します。

前に試したChat.jsに、react-native-websocketではなく、素のWebSocketを使うように処理を追加すればできる気になってきました。
やってみます。


以下は、無駄になったreact-native-websocketのインストール方法です。読み飛ばしてください。




◆react-native-websocketのインストール(不要です)
以前、React Nativeのテンプレート環境にreact-native-gifted-chatをインストールしたときのやり方でいいのかと思います。
コマンドプロンプト(管理者権限)を起動して、以下の如く。
----コマンドプロンプト-----------------------------
C:\WINDOWS\system32>cd /d D:\AppMake\proj\VTChat

D:\AppMake\proj\VTChat>npm install react-native-websocket --save
npm WARN @typescript-eslint/eslint-plugin@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN @typescript-eslint/parser@1.13.0 requires a peer of eslint@^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN eslint-plugin-react@7.12.4 requires a peer of eslint@^3.0.0 || ^4.0.0 || ^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN eslint-plugin-react-native@3.6.0 requires a peer of eslint@^3.17.0 || ^4 || ^5 but none is installed. You must install peer dependencies yourself.
npm WARN tsutils@3.17.1 requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ react-native-websocket@1.0.2
added 1 package from 1 contributor and audited 952806 packages in 81.028s
found 4 low severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details
---------------------------------------------------

できたっぽいです。
「(プロジェクトフォルダ\node_modules」の下に「react-native-websocket」というフォルダが作成されています。





スマフォ・アプリ側にWebSocket通信の処理を実装します。・・・

続きを読む



スマフォのアプリを作りたい(11):React Nativeでチャットアプリ味見④

   プログラミング [2020/02/04]
ちょっと、もうタイトル長過ぎ。
なので、「④」で済ませちゃってますが、つまり、こういうことです。
Start
 →スマフォのアプリを作りたい
  →スマフォ側の環境はReact Nativeを使用します
   →試しにチャットアプリでReact Nativeコードを味見して見ます
    →スマフォ側のUIをサンプル・コードで動かしてみました
     (react-native-gifted-chatを使ったサンプル)
    →サーバ側を準備したいと思ってます
←今回はココ


◆チャットサーバを準備するには
どんな環境があるのか?

-チャット的な動きをさせるための通信プロトコル?規格?-
XMLHttpRequest:JavaScriptなどのウェブブラウザ搭載のスクリプト言語でサーバとのHTTP通信を行うための、組み込みオブジェクト(API)である。 すでに読み込んだページからさらにHTTPリクエストを発することができ、ページ遷移することなしにデータを送受信できるAjaxの基幹技術である。
→レスポンス性能的にちょっと難があるそうな。

WebSocket:ウェブアプリケーションにおいて、双方向通信を実現するための技術規格である。XMLHttpRequestの欠点を解決する技術。
→上記の「難」を解決するんだって。

-チャット等を実現するためのフレームワーク?サービス?-
Rails:Ruby on Railsのこと。Rubyでできたフレームワーク(ライブラリ群?)
→Rubyで作る気はない。

Pusher:websocketを提供するAPIで、アカウント登録することで無料である程度使える。
→「ある程度無料で」とあるので、どっからか有料になっちゃうのかな。

Firebase:Googleが提供している、すばやく高品質のモバイルアプリやWebアプリケーションを開発することができるプラットフォーム(クラウドサービス)です。Firebaseを使うことで、開発者はアプリケーションの開発に専念でき、バックエンドで動くサービスを作成する必要も管理する必要もありません。
→検索するとこれを使ったという事例が多かった気がする。環境全てが楽に手に入りそう。無料プランでもかなり使えそう。

RatChet:WebSocketを介してクライアントとサーバー間でリアルタイムの双方向アプリケーションを作成するツールを開発者に提供する疎結合PHPライブラリ。MITライセンス。
→きっと、Firebaseに比べたら難儀しそうだけど。全体把握(保守性)&ランニングコストのことを考えた場合、これでいっかなぁ。

まだまだ、色々とあるみたいでしたが、PHPでただっぽいRatChetを使ってみることにします。

◆Eclipse環境を復活させる
以前使ってたサーバ・スクリプト開発環境のEclipseを復活することにしました。
(スマフォ・アプリ環境をタブレットにインストールしようとして迷走していた時、タブレットのディスク容量不足のために一旦アンインストールしてしまってました。今度は1TBの増設SSDを接続してあるし、余裕で入るでしょう。)

参考:https://mergedoc.osdn.jp/
さるの場合、上記のサイトから、「Eclipse 4.7 Oxygen」を選択し、次の画面の(Download)ボタンが沢山並んでいるところの「Windows 64bit-full edition」行の「Ultimate」列の[Download]ボタンを選んで、ダウンロードを実施しました。以前と同じVersionを選択したのは、やはり少し慣れがあるからです。

インストールは、ダウンロードしたpleiades-ultimate-win-64bit_jre.zipを解凍するだけです。
ただし、あんまりパスが深いところになると、実行時に問題があるという話が以前はありました。
.zipをダブルクリックすると、解凍先を指定するダイアログが出ます。
指定したパスの下に「pleiades」という名前のフォルダが作成されて、その下に展開されます。

以下2つのショートカットをディスクトップとかに作っておくと便利です。
(インストール先フォルダ)\pleiades\eclipse\eclipse.exe
(インストール先フォルダ)\pleiades\xampp\xampp-control.exe

次は、・・・

続きを読む



スマフォのアプリを作りたい(10):React Nativeでチャットアプリ味見③

   プログラミング [2020/01/30]

やっと、サンプルのチャットプログラム(UIのみ評価可)を想定通りに確認できたので、
次は、実際にサーバ側も用意して通信周りもどうなっているのか見たいと思ってます。

その前に、少し気になったエミュレータ上での音声入力(認識)がどうなっているのかちょっと確認します。
【前提】
・Android Virtual DeviceのAndroid 6.0(エミュレーター)についての話です。
・Windows10のタプレットPC上で動作させています。

◆日本語キーボードでの音声入力呼出し
英語版のソフトウェアキーボードには、右上の方にマイク・アイコンがあって、音声入力画面に簡単に変えられました。
でも日本語版キーボードにしたら、マイクアイコンが見当たりません。
20200130_3.jpg

日本語(IME)キーボードの場合、
-左下の「文字あA1」と書かれている(切替え)ボタンを長押しする
-「入力オプション」ポップアップから「入力方法の選択」メニューを選択
-さらにリストの中から「Google音声入力」を選択
で、音声入力ができるそうです。
やってみましたが、キーボード・レイアウトを変更するのみで、音声入力に繋がるようなメニューは出てきませんでした。
Androidのバージョンの制限なのか、AVD(エミュレータ)上での制限/不足なのかは分かりません。

別のサイトでは、「Google日本語入力」というIMEをインストールする必要があると書いてあったので、Googleのダウンロードサイトからダウンロードしてインストールを試みましたが、「デバイスが対応してない」的なメッセージが出て失敗しました。

日本語ソフトキーボードからの音声入力の呼び出しは一旦諦めます。

母艦PCに接続したマイクから音声入力がそもそもできるのか・・・?

続きを読む



スマフォのアプリを作りたい(9):React Nativeでチャットアプリ味見②

   プログラミング [2020/01/29]
前回、とあるサイトを丸っとマネして、チャット風アプリをエミュレータ(AVD)上で実行するところまでやりました。
★1:https://qiita.com/Yorinton/items/b029df0713a471d4569a
でも、上記サイトで説明しているような表示になりませんでしたし、「実際チャットできるようにするには?」まで到達してません。
よって、前回の続きになります。

念のため:さるが調べて/試して分かったことを簡潔にメモしてるわけではありません。ボヤキや迷走具合をそのままダラダラ書いてます。読んでるとイライラするかと思います。悪しからず。


前回のサンプルプログラムの問題を解決するには、サンプルコードの理解からです。
コード内容全体は前回の書き込み「スマフォのアプリを作りたい(9)・・・」か★1サイトをご参照ください。

◆チャットサンプルのApp.js
React Nativeのテンプレートサンプルでは、メインの処理「App」は関数として定義されていました。
const App : () => React$Node = () => {・・・}
でも、チャット・サンプルでは、コンポーネントになってました。
class App extends Component<{}> {・・・}
なぜでしょう。深く考えなくてもいいんでしょうか。
念ためのご参考:https://mae.chab.in/archives/2956
「コンポーネント」にはClassとFunction(関数)が含まれるんですね。
少し役割も違うようですが、トップのレイヤーの定義なんでどっちでもよさそうですね。

それにしたって、Componentの後ろの<{}>さるには理解不能です。
だいぶ、この書き方について解説してくれてるところを探しました。
唯一、「extends の後では任意の式が指定できます。」と説明してくれてるところを見つけました。
参考:https://ja.javascript.info/class-inheritance
それと、classの基本的なこと。
参考:https://qiita.com/tadnakam/items/ae8e0e95107e1427983f
どっちにしろ<{}>の意味は掴めません。
{中身}に何も入ってないから気にしなくていいのかな。
あまりに消化不良すぎるので、さらに検索したら、TypeScriptという単語が引っ掛かりました。
「うゎ、出たTypeScript」とか思ったのですが、何なのかはよく知りません。
Flowの件を調べているときに、引き合いに出されていた記述を見たので、Flowと横並びな感じの表現手法のようなイメージです。
TypeScriptって?
「Microsoftによって開発・発表されたプログラミング言語です。JavaScriptを拡張して作られたものですが、JavaScriptとは違い静的型付けのクラスベースオブジェクト指向言語になっています。TypeScriptをコンパイルすると、JavaScriptのコードに変換されるためJavaScriptが動く環境であればすぐに使うことができます。」
参考:https://www.sejuku.net/blog/93230

ともかく、class定義の基底クラス名の後に<>がつくときの大まかな意図は以下の解説でなんとなく分かった気になりました。ただし、そこまでです。
参考:https://qiita.com/alfe_below/items/1cb81a6a03d8d6d73b27
FlowにTypeScript・・・もう勘弁してくだせー。さるには無理です。

プチ勉強したReactと違うと思えたところ
・Appの呼び出し(サンプルなので単に「一例」ということかもしれません。)
  React:ReactDOM.render(<App … />, document.getElementById('root'))
  ReactNative:AppRegistry.registerComponent(appName, () => App);


Appコンポーネントのrender()メソッドのreturn(中身)は、以下になってます。
----JSX:App.js:-----------------------------------
<Router>
<Scene key='root'>
<Scene key='Chat' component={Chat} title='チャット'/>
</Scene>
</Router>
--------------------------------------------------

使っているのは、追加フレームワーク:react-native-router-fluxの中のコンポーネントですね。
従って、「react-native-router-flux」でぐぐりました。
参考:https://qiita.com/YutamaKotaro/items/ab52b6ba664d88a87bd9
Reactのお勉強時に参考にしたサイトでルーティングの話が出てきたが、React Ntive(クライアント・アプリ)でも必要なん?
上記のサイトの説明にあるように、「戻る」機能とかを実装するときに便利なのかもしれないですね。

使っている<Router><Scene>については、
切り換え先候補を<Scene>で定義して、それが複数あるときのルーティング(戻る:< とか)が使えるようにするために<Router>で囲うみたいです。
<Scene>は、遷移コンポーネントを列挙する場合と、その列挙したリストをグルーピングする場合に使うようです。
今回のチャットサンプルでは、<Scene key='root'>で「root」という最初の選択グループを作成し、そのグループ内に指定した<Scene key='Chat' ・・・ />で遷移先候補の実際のコンポーネントを指定します。
<Scene>の「key=」は行先としての「識別子」で、「component=」が行先コンポーネントを示します。「title=」は行先の「タイトル」ですね。
複数の<Scene>がある場合は、「initial」属性を指定して最初に動作するコンポーネントを指定するようですが、このサンプルでは1つしかないので、省略してます。つまり自動的に「Chat」という名前のコンポーネントを実行するようになっているのかと思います。

例えば、上記サンプルの「<Scene key='Chat' initial component={Chat} title='チャット'/>」と同じ並びで、「<Scene key='Search' component={Search} title='検索'/>」とかがあった場合、ChatコンポーネントからSearchコンポーネントへの遷移動作は、Chatコンポーネント側に無ければいけないみたいです。

このサンプルにおいては、全てはChat.js側ですね・・・

続きを読む



スマフォのアプリを作りたい(8):React Nativeでチャットアプリ味見

   プログラミング [2020/01/24]
単純に考えれば、チャットを不特定多数で行う場合は、サーバーが必要なんですよね?

それはさて置き、「React Native チャット」をキーワードにして検索すると、「簡単にできます」調のサイトが見つかります。
その内の1つ、以下のサイトを参考にやってみました。
★1:https://qiita.com/Yorinton/items/b029df0713a471d4569a
※ここの事例はUIだけなのかな?
 この時点でまだ斜め読みした程度でしか内容は理解してません。いくつかの追加のフレームワーク(ライブラリ)をインストールするように書いてあります。


◆準備(追加インストール)
react-native-gifted-chatのインストールはコマンドプロンプトからnpmコマンドを打つだけのようだったので早速やってみました。
でもエラーになりました。
----JSX:------------------------------------------

45 verbose node v12.13.1
46 verbose npm v6.12.1
47 error code ENOENT
48 error syscall spawn git
49 error path git
50 error errno ENOENT
51 error enoent Error while executing:
51 error enoent undefined ls-remote -h -t https://github.com/EvanBacon/react-native-parsed-text.git

--------------------------------------------------

undefinedと言ってます。何が・・・・「git」っていうやつか?
じゃあインストールしてみっぺか。

続きを読む



スマフォのアプリを作りたい(7):React Nativeのテンプレートを読む

   プログラミング [2020/01/23]
前回、ReactのJavaScriptの記述の文法?・・・というか書き方についてちょっとだけお勉強してみました。
で、いよいよReact Nativeのコードサンプルについて見てみます。
でも、前回のお勉強だけでは足りませんでした。
見れば見るほど分からないことだらけで、また発散しまくってます。

ここで、前回のお勉強経緯の説明でも流してきた用語についてちょっとだけ注釈しておきます。
ES6:ESはECMAScriptの略。ECMAはEuropean Manuufacturer Associationの略で国際標準規格。(頭に「欧」って付いてるけどね。)ECMAScriptはJavaScriptの標準規格。ES6はES2015のことで、2015年にリリースされた規格。


React-Nativeアプリ(テンプレート)のソース構成(一部)は、
 ・index.js   :エントリスクリプト
 ・app.json   :プロジェクト(プログラム名)を規定しているデータファイル
 ・App.js    :アプリの処理本体
 ・.flowconfig  :Flowによるチェック動作のパラメタ/オプション指定
 :

なんかが含まれているようです。
使われ方は、以下のボヤキの中に順次出て来たり来なかったり。


◆index.js
プロジェクト・フォルダ直下にあった、index.jsは以下の内容でした。
これが、このアプリのオオモトですよね。きっと。
----JSX:------------------------------------------
/**
* @format
*/

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);
--------------------------------------------------

最初のimportは、React Nativeのコードとしては必須の記述でしょう。たぶん。
「AppRegistryという名前のコンポーネントを使う」宣言ですね。
2番目は、このアプリ固有の処理コードを含むApp.js(入口コード)なので、至極当然。
3番目は、app.jsonは、以下の内容でした。
----JSON:-----------------------------------------
{
"name": "VTChat",
"displayName": "VTChat"
}
--------------------------------------------------

nameというキー(名前)に"VTChat"というバリュー(値:プロジェクト名)が割り当ててあります。
それをindex.js上では、appNameという名前で参照できるようにしてるんですね。
.jsonファイルをimportするだけで、中のデータを使えるということを今初めてしりました。
ただし、さるには.jsonが「XML的にデータ構造を階層化して記述できる形式/ファイル」くらいの認識しかありません。

でもって、react-nativeに含まれるAppRegistry.registerComponent()メソッドを呼び出してるところでこのファイルは終わりです。
AppRegistry.registerComponent()はこのアプリのエントリーポイントを指定するメソッドだそうです。
つまり、App.jsに含まれるAppというコンポーネントを呼び出すようにしてるんですね。
AppRegistry.registerComponent("アプリ名", () => コンポーネント名);

※App.jsを見ると「App」は関数として定義されている感じ。React Nativeでは「関数」と「コンポーネント」は同義?

話を戻します。index.jsはAppRegistry.registerComponent()以外は他に何もしてない。

つづいて・・・

続きを読む



スマフォのアプリを作りたい(6):React NativeのJavaScriptって?

   プログラミング [2020/01/20]
前回までで、なんとなく開発環境ができたっぽいので、React Nativeで書くコードはどんな?から勉強していきます。
ですが、React Nativeを理解する場合、「Reactを知っていると入り易い」とどこぞに書いてあったので、ちょっと遠回りになるかもしれませんがReactの概要を各入門サイトを読んで見ました。

ただし、さるなので、HTML、JavaScript、さらにWebに関する知識は、古く、乏しく、いい加減なので、根本から分からないことだらけです。なので途中途中「えっそこから?」的な備忘も多いし、発散ぎみであることを最初に申し上げておきます。肝心なことは、参考にさせていただいたサイトのURLを記載しておりますので、そちらを参考になさってください。

◆Reactとは
参考サイトは以下で、以下のサイトの説明で分からなかった点の補足と勝手な解釈を以降記載しています。
★1:http://www.tohoho-web.com/ex/react.html#whatis
・Facebookが開発?/考案した、Webアプリを開発するためのJavaScriptベースのフレームワークだそうです。
・JavaScriptはES6の文法を用い、JSXを利用することができるとありました。(JSX:言語という言い方をしている場合もあったが、JavaScript中にHTML/XMLを直接的に記述できる表記法と言ってもいいんでは・・・。)
・ES6文法やJSXで記述されたコードは、Babelというトランスパイラ?で実行時にJavaScript ES5の記述に置き換えられる。
・Chrome、Firefox、IE10以降で動作する。
・MITライセンスで商用利用可。

◆Reactを試しに実行してみるサンプル
★1のサイトを一通り読んだが、さるなので、何かわからない言葉/用語を調べると次から次へと不明な用語が出てくる感じでした。

まずは★1の最初のサンプルを見ればなんとなく分かるのが、
通常のHTMLと同じで、.htmlがあって、その中にJavaScript部分で組まれたコードがクライアント側で動作すると解釈しました。
ちょっと脱線-CDN?→<script crossing ... >?→CORS?→Origin?
「CDN」とタイトルされているサンプルコードをなんとなく理解するのに上記を芋づる調べする羽目になりました。
・Origin:プロトコル、ドメイン、ポートの組み合わせで表されるリクエスト先(httpX://xxx.xxx.xx.xx:pppp)
・CORS:Cross-Origin Resource Sharingの略。オリジン間リソース共有。異なるオリジンにあるリソースをリクエストするときに、ブラウザに対してそのリソースへのアクセス権を与えるように指示する仕組み。
・crossing属性:属性値にはanonymousとuse-credentialsがあり、anonymousを指定した場合、ユーザ認証情報は送付されない。use-credentialsは資格情報が送付される。
・CDN:Content Delivery Networkの略。コンテンツを配信する際に、エッジサーバと呼ばれるリクエスト元に近いサーバーにコンテンツのコピーを置き、そこからコンテンツを配信する手法?/サービス?。DNS内に指定されたURLの代理(エッジサーバ)が登録されており、そのエッジサーバへのアクセスを誘導する。エッジサーバは、CDNキャッシュサーバとも言うらしい。
参考:https://knowledge.sakura.ad.jp/19191/


要は、実行時に取り込むReactのフレームワーク/ライブラリを使うためには、Reactのスクリプトを実行する際に以下の6~8行目の記述が必要ということのようです。開発時用と実際に稼働させる用とあるそうです。(以下は実際に稼働させる用。)

----------------------------------------
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="UTF-8"><title>React Test</title></head>
<body>
<div id="root"> </div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"> </script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"> </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.10.3/babel.min.js"> </script>
<script type="text/babel">
ReactDOM.render(
<h1>Hello world!</h1>,
document.getElementById('root')
);
</script>
</body>
</html>
----------------------------------------

Reactの場合、<script type="text/babel">と指定しなくてはいけなくて、
トランスパイラBabelは、Ajaxのライブラリに含まれてんのね。

またちょっと脱線-Ajax
:Asynchronous JavaScript + XMLの略。ブラウザ内でJavaScriptの通信機能を使って、XML形式のデータを送受信する技術。
通常、何かsubmitして、宛先が現在と同じURLであるような場合、同じ内容のHTLM全体をレスポンスさせるのではなく、部分的な内容(例えば追加のメッセージ)のみで済ませることができる手法。非同期通信と呼んでいる。(※ちょっとAsynchronousという表現が分かりにくい。)
参考:https://qiita.com/Masaki_Mori07/items/8344d3ab87913b4189a4


まだまだ、レベルの低い備忘録が続きます・・・・

続きを読む



スマフォのアプリを作りたい(5):React Native環境でデバッガを動かしてみる

   プログラミング [2020/01/09]
前回の「続・続React Native環境構築」までで、何とかエミュレータを起動してサンプルプロジェクトを実行(表示)させるところまで来ました。

その続きになります。

エミュレータ上のサンプルプロジェクトの表示内容を見ると、何となくReact Nativeのチュートリアルになっているようです。
20191224_9.jpg

さるなので言われるがままやってみます。
(英語表記なんで、きっと誤解多いけど。)
※それと、後で出てきますが、デバッグするためにはChromeのインストールが必要です。

1)最初の説明「Step One」で、「App.jsを編集してみろ」みたいなことが書かれていてます。
プロジェクトフォルダ直下にApp.jsというソースがありました。
中身は、ほとんどチンプンカンプンですが、画面に表示している内容が記述されています。
「App.js」と書いてあるところを「app.js」に変更して、セーブしてみました。

2)エミュレータ上の説明の続きは「See Your Changes」とあり、「Rキーを二度叩け」と書いてあります。
二度叩いてみると、「Step One」でやった表示内容の変更が反映されました。

3)その続きの説明で「Debug」とあり、「CmdかCtrl+mか・・・」とあります。
[Ctrl]+[M]を押してみましたが、・・・ブラウザに何やら出ました。

オンラインで何かするのか???・・・・・

続きを読む



カレンダー
05 | 2020/06 | 07
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 - - - -
プロフィール

さるもすなる

Author:さるもすなる
さるです。別HPサイト「さるもすなる」から侵食してきました。 山菜/きのこ、それとタイトルにしたPPバンド籠のことをメインに徒然に・・・・暇を持て余したさるの手仕事:男手芸のブログってことで。

最新記事
最新コメント
月別アーカイブ
カテゴリ
天気予報

-天気予報コム- -FC2-








本家のHPのトップ
山菜や茸の話です
PPバンドの籠作品と作り方です
投稿をお待ちしております



ブログランキング・にほんブログ村へ にほんブログ村 ハンドメイドブログへ



マニュアルのお申し込み



検索フォーム
リンク
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR