20210611のJavaに関する記事は6件です。

Speech Recognizerの謎のエラーとAPIレベル

はじめに 結論から言うと、AndroidManifest.xmlへの記述が足りませんでした。 「何だそんなことか」と思われるかもしれませんが(実際自分も思いましたが)、エラーを見るとすぐに「プログラム側がおかしいに違いない!」とその他の部分をよく見ない癖があり、それを直さないと大切なことを見落とすよという自戒を込めて書き記しておきます。 いやでもほんと、書くのすら恥ずかしい失敗なんです//// では以下、お付き合いください。 環境 Android Studio 4.2.1 〜動かないスマホ〜 docomo Galaxy S20+ 5G SC-52A Android 11 APIレベル:30 docomo Galaxy Note20 Ultra SC-53A Android 11 APIレベル:30 〜動くスマホ〜 docomo arrows NX F-01K Android 9 APIレベル:28 docomo Xperia ACE SO-02L Android 10 APIレベル:29 この時点で「あっ・・・」って気づくべきでした エラー内容 2021-06-11 21:39:11.127 30307-30307/{パッケージ名} E/SpeechRecognizer: bind to recognition service failed 直訳すると認識サービスへのバインドに失敗しましたという意味。 この時点でMediaPlayerを疑い始めるという無能っぷり・・・ 焦るとプログラム側しか見えなくなるのはマジで直した方が良いですね・・・ 状況 問題発生時に書き記したものがこちら↓ ほぼ同じコードを持つアプリの音声認識の起動は成功する ただし問題のあるアプリのコードや状態を成功するアプリと全く同じにしても音声認識は起動しない 新しく起動に成功するアプリの状態を丸々コピーしたアプリも音声認識の起動に失敗する 音声合成サービスを正しく起動できる機種・できない機種がある こうなって「当然」な間違いを犯してるんですよね・・・ やったこと こちらも問題発生時に書き記したものがこちら↓ Splash画面の排除 関係ないとは思いつつ、直近で追加したアプリ起動時のスプラッシュ画面を排除しました。 が、状況は変わらず Media Playerの排除 まさか音声系+音声系でどこかぶつかっているのかと思い、MediaPlayerを排除しましたが、状況は変わりませんでした。 ちなみにテストで入れたコードなので、どのみち今後排除する予定ではあります 作り直し 新たなプロジェクトで音声認識に成功する旧バージョンのアプリのコードをコピペ、実行しました。 が、結果は変わらず 当たり前なんだよなぁ・・・ 結論 AndroidManifest.xmlに以下の記述をしていなかった <queries> <intent> <action android:name="android.speech.RecognitionService" /> </intent> </queries> どういう意味? Speech Recognizerを利用する際、Android 11(APIレベル30)以降は上記の記述をしなければ利用できないようです。 記述すべきものを記述していないのだから使えないのは当然です。 滑稽な慌てようを振り返ろう arrows NX F-01K・Xperia ACEで使えたが、Galaxy S20+ 5GとGalaxy Note20 Ultraでは使えない 所有するGalaxyは最新のAndroid11、Xperia ACEはAndroid10、arrowsはAndroid9。 10以前はqueriesの記述が不要なので使えるのは当然 やったこと欄 全く関係無いです。 旧バージョンでは使える 旧バージョンのアプリのManifestにはしっかりとqueriesを記述していたから使えて当然 作り直した方には記述されていないから使えなかった まとめ プログラム以外にも目を向けよう 決めつけはよくない 常に最新の情報を入手しよう ちなみに問題解決までに約6時間かかりました。 このエラー自体が初歩的すぎてどこにも情報がなく、中国語や英語のサイトを見ても「カスタムROM搭載」「Speech Recognizerが使えない端末」といったような情報ばかりが出てきてなかなか同じ状況の人が居ないのも焦りに拍車をかけていた気がします・・・ 今回の事件でコード以外の部分に目を配らないと行けないことがよく分かったので、今後は同じミスを犯さないように気をつけたいと思います・・・ 以上、超恥ずかしいミスを6時間も掛けて解決した話でした。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

try-catch-finallyブロックについて

try-catch-finallyブロックについて try-catch-finallyブロックによる例外処理 Java言語には例外処理を行う方法が2つあります。 ・try-catch-finallyブロックによる例外処理 ・throwsキーワードによる例外処理 今回は「try-catch-finallyブロック」の説明をしていきます。 try-catch-finallyブロックの構造 以下のコードをご覧ください。 void method(){ try{ 例外が発生しそうな処理 }catch(例外クラス名 変数名){ 例外が発生したときの処理 }finally{ 必ず実行したい処理 } } 各ブロックの役割は、次の通りです。 ・tryブロック ⇨ 例外が発生しそうな箇所をtryブロックで囲む ・catchブロック ⇨ 例外は発生したときの処理をcatchブロックの中に定義する ・finallyブロック ⇨ 例外が発生しなくても必ず実行したい処理をfinallyブロックに定義する Java実行環境からスローされてきた例外のオブジェクトを受け取るのが、catchブロックの役割です。 catch(例外クラス名 変数名){} 例外クラス名は、Javaには例外クラスというものが存在しそれを上記に定義します。 try-catch-finallyブロックの組み合わせ try-catch-finallyのすべてのブロックを記述する必要はありません。 次の組み合わせが可能です。 ・try-catch ・try-finally ・try-catch-finally ただし、注意点として、tryブロックのみの定義はコンパイルエラーとなります。 まとめ ・Javaの例外処理には2通り存在する。「try-catch-finallyブロック」「throwsキーワード」 ・tryには例外が発生しそうな箇所をtryブロックで囲む ・catchブロックには例外は発生したときの処理をcatchブロックの中に定義する ・finallyブロックには例外が発生しなくても必ず実行したい処理をfinallyブロックに定義する ・try-catch-finallyのすべてのブロックを記述する必要はない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaでもSymbolブロックチェーン~送金編~

Symbol from NEMではエンタープライズ分野で人気のあるJava言語でも使用することができます。 今回はJavaでSymbol送金を体験してみましょう。 まず、公式の案内通りにGradleの準備をします(Gradle 7.0 以上) ここで dependencies { compile "io.nem:symbol-sdk-vertx-client" } とありますが、これでは動きません。 implementation 'io.nem:symbol-sdk-vertx-client:1.0.0' と読み替えてください。 gradle run が実行できるようになったらApp.javaを書き換えていきます。 基本プログラム package symbol_test; public class App { public static void main(String[] args) throws Exception { run(); } public String getGreeting() { return "Hello Symbol!"; } private static void run() throws Exception { Thread.sleep(1000); run(); } } これが基本フォーマットになります。 public static void mainからプログラムが開始され runで強制終了されるまでループします。 送金プログラムだけの場合はループは必要ありませんが、着金を検知するためにループで待機しています。 import 今回使用するライブラリです。 import java.time.Duration; import java.math.BigInteger; import java.util.Collections; import io.nem.symbol.sdk.api.Listener; import io.nem.symbol.sdk.api.RepositoryFactory; import io.nem.symbol.sdk.api.TransactionRepository; import io.nem.symbol.sdk.model.account.Address; import io.nem.symbol.sdk.model.account.Account; import io.nem.symbol.sdk.model.mosaic.Mosaic; import io.nem.symbol.sdk.model.mosaic.MosaicId; import io.nem.symbol.sdk.model.message.PlainMessage; import io.nem.symbol.sdk.model.network.NetworkType; import io.nem.symbol.sdk.model.transaction.Deadline; import io.nem.symbol.sdk.model.transaction.Transaction; import io.nem.symbol.sdk.model.transaction.SignedTransaction; import io.nem.symbol.sdk.model.transaction.TransferTransaction; import io.nem.symbol.sdk.model.transaction.TransferTransactionFactory; import io.nem.symbol.sdk.infrastructure.vertx.RepositoryFactoryVertxImpl; python版では対話式に都度ライブラリを追加していきましたが、 Javaでは最初に宣言しておきます。 リポジトリ生成 RepositoryFactory repo = new RepositoryFactoryVertxImpl( "http://ngl-dual-101.testnet.symboldev.network:3000" ); 接続するノードを指定してレポジトリを生成します。 アカウント生成 Account alice = Account.createFromPrivateKey( "896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED512****", NetworkType.TEST_NET ); System.out.printf("Alice address is: %s \n",alice.getAddress().plain()); Account bob = Account.generateNewAccount(NetworkType.TEST_NET); System.out.printf("Bob address is: %s \n",bob.getAddress().plain()); 送金者Aliceと受信者Bobを生成します。送信者は残高を持つ秘密鍵から生成。Bobはランダムに生成しました。 トークン定義 BigInteger amount = BigInteger.valueOf(1); Mosaic mosaic = new Mosaic( new MosaicId("091F837E059AE13C"), amount.multiply( BigInteger.valueOf(10).pow(6) ) ); 送金するトークンを定義します。 テストネットのXYMはID:091F837E059AE13C 可分性:6で定義されています。 公式ドキュメントは古いテストネットのIDで解説されているのでご注意ください。 トランザクション生成 TransferTransaction tx = TransferTransactionFactory.create( NetworkType.TEST_NET, Deadline.create(repo.getEpochAdjustment().toFuture().get()), bob.getAddress(), Collections.singletonList(mosaic) ).message( PlainMessage.create("This is a test message") ).maxFee(BigInteger.valueOf(2000000) ).build(); 送金トランザクションを生成します。 このあたりは公式ドキュメントの情報が古いので、少し変更が必要です。 - Deadlineを指定してください(引数にはネットワークのエポックタイムの指定が必要です)。 - メッセージはcreateの引数ではなく、メソッドチェーンで追加していきます。 署名とアナウンス String generationHash = repo.getGenerationHash().toFuture().get(); SignedTransaction signedTx = alice.sign(tx, generationHash); System.out.printf("SignedTransaction is: %s ",signedTx.getHash()); TransactionRepository txRepo = repo.createTransactionRepository(); txRepo.announce(signedTx).toFuture().get(); 作成したトランザクションをAliceで署名してネットワークにアナウンスします。 着金検知 Listener listener = repo.createListener(); listener.open().get(); listener.confirmed(bob.getAddress()) .subscribe( (notice) -> { System.out.println(notice.getType().toString());}, (e) -> { System.out.println(e);} ); リスナークラスを利用してBobへの着金を検知します。 Listener.confirmedで承認されたトランザクションが検知できます。 この書き方はVistiel Archさんの記事を参考にさせていただきました。 最後に全ソースコードを載せておきます。 ぜひみなさん、お試しください! package symbol_test; import java.time.Duration; import java.math.BigInteger; import java.util.Collections; import io.nem.symbol.sdk.api.Listener; import io.nem.symbol.sdk.api.RepositoryFactory; import io.nem.symbol.sdk.api.TransactionRepository; import io.nem.symbol.sdk.model.account.Address; import io.nem.symbol.sdk.model.account.Account; import io.nem.symbol.sdk.model.mosaic.Mosaic; import io.nem.symbol.sdk.model.mosaic.MosaicId; import io.nem.symbol.sdk.model.message.PlainMessage; import io.nem.symbol.sdk.model.network.NetworkType; import io.nem.symbol.sdk.model.transaction.Deadline; import io.nem.symbol.sdk.model.transaction.Transaction; import io.nem.symbol.sdk.model.transaction.SignedTransaction; import io.nem.symbol.sdk.model.transaction.TransferTransaction; import io.nem.symbol.sdk.model.transaction.TransferTransactionFactory; import io.nem.symbol.sdk.infrastructure.vertx.RepositoryFactoryVertxImpl; public class App { public static void main(String[] args) throws Exception { RepositoryFactory repo = new RepositoryFactoryVertxImpl( "http://ngl-dual-101.testnet.symboldev.network:3000" ); Account alice = Account.createFromPrivateKey( "896E43895B908AF5847ECCB2645543751D94BD87E71058B003417FED512314AE", NetworkType.TEST_NET ); System.out.printf("Alice address is: %s \n",alice.getAddress().plain()); Account bob = Account.generateNewAccount(NetworkType.TEST_NET); System.out.printf("Bob address is: %s \n",bob.getAddress().plain()); BigInteger amount = BigInteger.valueOf(1); Mosaic mosaic = new Mosaic( new MosaicId("091F837E059AE13C"), amount.multiply( BigInteger.valueOf(10).pow(6) ) ); TransferTransaction tx = TransferTransactionFactory.create( NetworkType.TEST_NET, Deadline.create(repo.getEpochAdjustment().toFuture().get()), bob.getAddress(), Collections.singletonList(mosaic) ).message( PlainMessage.create("This is a test message") ).maxFee(BigInteger.valueOf(2000000) ).build(); String generationHash = repo.getGenerationHash().toFuture().get(); SignedTransaction signedTx = alice.sign(tx, generationHash); System.out.printf("SignedTransaction is: %s ",signedTx.getHash()); TransactionRepository txRepo = repo.createTransactionRepository(); txRepo.announce(signedTx).toFuture().get(); Listener listener = repo.createListener(); listener.open().get(); listener.confirmed(bob.getAddress()) .subscribe( (notice) -> { System.out.println(notice.getType().toString());}, (e) -> { System.out.println(e);} ); run(); } public String getGreeting() { return "Hello Symbol!"; } private static void run() throws Exception { Thread.sleep(1000); run(); } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初めてEclipsを触り、動的Webページを作る

Eclipsのインストール 全部入ってるパッケージであるPleiades All in Oneをインストールした。 Pleiades = Eclipsに主要なプラグインを追加したもの(日本語になっている) All in One = web開発に必要なTomcat、フレームワークのSTS(Spring)も入っている。 eclips単体で元々インストールしていたら、後からPleiadesプラグインだけインストールすることもできる。 Eclipsの使い方(Tomcatアプリの作り方、HelloWorldまで) 下記参照した。 https://searchman.info/java_eclipse/1100.html つまったところと解決策 上記サイト丸々コピーではなく、自分の作りたいアプリケーションのファイル命名に合わせた。そのためweb.xmlの記述内容やブラウザへのURL指定が間違っており、ブラウザ表示できなかった。 web.xml <servlet-class> パッケージ名.クラス名 </servlet-class> ブラウザへの指定URL http://localhost:8080/プロジェクト名/web.xmlで指定したurl-pattern 次の課題 jspファイル追加 補足:混乱しやすいのでメモ 動的ページは ・javaファイル(データ受け渡しなど裏方専門) ・jspファイル(ブラウザ表示など表専門) この二つでセットになっており、 URLに指定したパスがどのクラス(javaファイル内に記載されている)を呼び出すかを ・web.xml のなかで指定する。 呼び出されたjavaファイル内のクラスがjspファイルを呼び出し、ブラウザ表示に至る。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初めてEclipseを触り、動的Webページを作る

このサイトのとおりに進めています 他のサイトも参考にしながら、大筋はこちらを参照した。 https://www.kkaneko.jp/pro/tomcat/eclipsetomcat.html Eclipseのインストール 全部入ってるパッケージであるPleiades All in Oneをインストールした。 Pleiades = Eclipseに主要なプラグインを追加したもの(日本語になっている) All in One = web開発に必要なTomcat、フレームワークのSTS(Spring)も入っている。 すでにeclipse単体で元々インストールしていたら、後からPleiadesプラグインだけインストールすることもできる。 Eclipseの使い方(Tomcatアプリの作り方、HelloWorldまで) 下記参照した。 https://searchman.info/java_eclipse/1100.html Eclipse内部Tomcatサーバ設定→パースペクティブをJava EEに変更→動的Webプロジェクト作成 出会ったエラー(と解決策)(解決していないもの多々) 1.参照サイト丸々コピーではなく、自分の作りたいアプリケーションのファイル命名に合わせた。そのためweb.xmlの記述内容やブラウザへのURL指定が間違っており、ブラウザ表示できなかった。 web.xml <servlet-class> パッケージ名.クラス名 </servlet-class> ブラウザへの指定URL http://localhost:8080/プロジェクト名/web.xmlで指定したurl-pattern 2.eclipseを再起動したところ、内容を変更していないのにweb.xmlの内でエラー表示が出た。改行したらエラーは消えた。原因不明。 3.Tomcatを起動した後、http://localhost:8080/でブラウザ更新してもTomcatの接続確認ページが表示されない。404が出てしまう。(未解決) 4.Tomcatは起動しているが、servlet.javaファイルが実行できない。404が出てしまう。 アノテーションでルーティングしていたが、web.xmlにも追記してみた。→むしろサーバー起動すらしなくなった。 web.xmlの追記部分をコメントアウトし、元の状態で再度実行をかけたら通った。原因不明。 次の課題 jspファイル追加 補足:混乱しやすいのでメモ 動的ページのしくみ ・javaファイル(データ受け渡しなど裏方専門) ・jspファイル(ブラウザ表示など表専門) この二つでセットになっており、 URLに指定したパスがどのjavaクラスを呼び出すかを ・web.xml のなかで指定する。(=マッピング定義) 呼び出されたjavaファイル内のクラスがjspファイルを呼び出し、ブラウザ表示に至る。 サーブレットとクラスを区別する考え方 どちらもjavaファイルで記述されるが、 サーブレットはURLとjavaクラスとのマッピングが必要になる。 Tomcatはどこにある? Eclipseの外にある公開Tomcatサーバと、Eclipseの内部にあるTomcatサーバのふたつ。 同時に起動するとポート番号の奪い合いになることがあるので注意する。 Eclipseのバージョンアップによるディレクトリ構成(フォルダ名)の変更 srcファイルその他のファイル名や位置が変わっていて、参考にしているサイトの記述との相違がある。 動的Webプロジェクトを作成すると、srcという名前のファイルが作られるはずが、 src/main/javaになっている。srcへの変更はできない。 参考サイトで認めるが自分のEclipse上で無くなっているファイル名 ・Javaリソース ・src ・WebContent 参考サイトで見たことのないフォルダ名 ・JREシステムライブラリー ・Apache Tomcat vx.x[Tomcatx(Javax)] Eclipse IDE 2021-03 (2021年3月17日)以降のバージョンで「動的および静的Webプロジェクトを作成するときに、推奨されるコンテンツパスとJavaソースフォルダーパスが変更されました」とのこと。 https://www.eclipse.org/webtools/releases/3.21/NewAndNoteworthy/#Modernized%20default%20paths 自分で置き換えて考えなくてはならず、つまづいているところがある。 まだ未解決。 下記参照した。 https://teratail.com/questions/337875 jspファイルから作成されたサーブレットクラスの場所 jspファイルを実行するとTomcatがそれをサーブレットクラスに変換、コンパイルする。 作成されたサーブレットjavaファイルとclassファイルは、 .metadata¥.plugins¥org.eclipse.wst.server.core¥tmp0¥work¥Catalina¥localhost¥プロジェクト名¥org¥apache¥jspにある。 jspファイルの修正が反映されない時などは、この中身を削除してみる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SQL】内部結合( INNER JOIN )とは

内部結合( INNER JOIN )とは 互いのテーブルに存在するデータのみを結合 ※ON ( 条件文 )で指定したデータがあるかないか 構文 SELECT 出力テーブル列名 FROM 対象テーブル1 INNER JOIN 対象テーブル2 ON テーブル1.列名 = テーブル2.列名; 実際にやってみる name テーブル id name code 1 うさぎ 1 2 へび 2 3 ぱんだ 1 4 らいおん 3 info テーブル code info 1 かわいい 2 かっこいい SELECT name.id, name.name, info.code, info.info FROM name INNER JOIN info ON name.code = info.code; 実行結果 id name code info 1 うさぎ 1 かわいい 2 へび 2 かっこいい 3 ぱんだ 1 かわいい らいおんの name.code と一致するデータが info.code に存在しなかった為、らいおんは結合されない
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む