月別アーカイブ 9月 2019

asaba 著者:asaba

【android】onSaveInstanceStateでメンバ変数を復元する

activityは、画像の回転やブラウザの移動に伴い、破棄されて新しいactivityに

生成されるライフサイクルを持っています。

仮に遷移前にメンバ変数を持っていた場合、移動後は基本destroyされ

またonCreateされるため、持っていた値が無かったことになり

全部消えてしまいます。

 

値を保存して新しいactivity生成時にまた同じ値を使いたいという時は、

onSaveInstanceStateを使って保存する方法があります。

保存対象は主にメンバ変数で、edittextやtextViewといったview系の値はviewが独自で

復元してくれるのでそちらは考慮する必要はないです。

ではどうやって保存するかというと、まずonSaveInstanceStateメソッドをこのように

書いていきます。

 


@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("str", mName);
savedInstanceState.putInt("int", mAge);
}

 

保存する値は、Bundleというクラスが持っているput○○というメソッドに

持たせて保存します。

この他にも、浮動所数点以下の値を保存できるputFloatや画像を保存する

putParcelableがあります。

 

後はどのタイミングで呼ばれるかですが、呼ばれる順番はonparseのすぐ後になります。

onparse->onSaveInstanceState->onDestroy->onCreate(新しいactivity作成)

と覚えていれば問題ないと思います。

 

次に保存した値をどうやって復元するかですが、onSaveInstanceStateで保存した値は

onCreate内でgetStringやgetIntしてメンバ変数に入れるだけで再利用することができます。

 

</pre>
//onCreate内

if (null != savedInstanceState) {
mName = savedInstanceState.getBoolean("str");
mAge = savedInstanceState.getInt("int");
}
<pre>

 

若しくはonRestoreInstanceStateを使って復元するか

 

</pre>
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mName = savedInstanceState.getBoolean("str");
mAge = savedInstanceState.getInt("int");
}
<pre>

 

注意点ですが、画像などのデータ量が大きいものを保存しようとすると

android.os.TransactionTooLargeException: data parcel size 32445533 bytesと

エラーを受けるので、どうしても再利用したい場合は必ずデータ量を小さくしたり

Uriのまま保存することをおすすめします。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】「Refused to load gap://ready because it does not appear in the frame-src directive of the Content Security Policy」エラーの対処法

Cordova で開発中のアプリを iOS で実行したところ、「Refused to load gap://ready because it does not appear in the frame-src directive of the Content Security Policy.」というエラーが発生しました。
Google翻訳にかけてみたところ、「コンテンツセキュリティポリシーの frame-src ディレクティブに表示されないため、gap:// ready の読み込みを拒否しました。」とのことでした。
HTML の Meta タグで指定している Content Security Policy に関する記述のところかとあたりをつけつつ、念のため検索。

こちらの記事がヒットしました。

iOSでRefused to load gap://ready because it appears in neither the child-src directive nor the default-src directive of the Content Security Policy. エラー
https://ufirst.jp/memo/2016/09/16/ios%E3%81%A7refused-to-load-gapready-because-it-appears-in-neither-the-child-src-directive-nor-the-default-src-directive-of-the-content-security-policy-エラー/

 

上記の記事によると、やはり Content Security Policy に関する記述に抜けがあったようで、frame-src の項目に gap://ready file: を追加し、再度実行したところ、今度は問題なくページが表示されました!
なお、記事内には default-src に追加とありましたが、私の環境では、frame-src の項目があったため、こちらに追加しました。
というか、frame-src がある状態で、default-srcgap://ready file: を追加してもこの設定は frame-src には反映されないので、今回のエラーは解決できません。

なので、gap://ready file: の記述は frame-src がある場合は frame-src に、frame-src がない場合は default-src に記述するようにしてください。

 

以上、Cordova アプリを iOS で起動した際に「Refused to load gap://ready because it does not appear in the frame-src directive of the Content Security Policy」エラーが発生するときの対処法でした。

  • この記事いいね! (0)
takahashi 著者:takahashi

redisを触ってみる 初期設定編

以前にも記事で取り上げたredisですが、いろいろきっかけがありまして実際に触ってみることにしました。

redisはNoSQLなデータベースサーバーなので、redisのサーバープロセスを立ち上げる必要があります。

ということで、まずはOSにredisをインストールします。

RedHat系(CentOSなど) の場合は

sudo yum install redis #インストール
sudo systemctl start redis #起動
sudo systemctl enable redis #自動起動に登録

debian系(Ubuntuなど)の場合は

sudo apt update #パッケージリスト更新
sudo apt install redis #インストール
sudo systemctl start redis-server #起動
sudo systemctl enable redis-server #自動起動に登録

mac OSでbrewコマンドが利用できる場合は

brew install redis #インストール
redis-server #フォアグラウンドで起動

とします。

インストールが完了すると、redisサーバー本体のredis-serverとredisを操作するクライアントであるredis-cliが利用できるようになります。

同じPC内でredisのサーバーとクライアント両方を動かす場合は、redis-serverが起動しているのを確認したうえで

redis-cil

とするだけでredis操作用のプロンプトに入ることができます。

ところで、redis-cliからリモートのredis-serverに接続しようとすると

こんな感じで、はじかれてしまいます。

redisはデフォルトでlocalhostからの接続のみ受け付けているため、外部からの接続を受け付けるようにするにはLANからの接続を受け付けるように設定する必要があります。

Ubuntuの場合は

/etc/redis/redis.conf

に設定があるので、vimなどでこのファイルを編集します。

編集するのは、上の画像にあるように “bind”と書かれている行です。

デフォルトでは 127.0.0.1 つまり、localhost(サーバー自身)からの接続のみしか受け付けない設定になっています。

外部からアクセスできるようにするには、redisが稼働するサーバーマシンのLANポート(NIC)に割り振られているIPアドレスを指定します。

例えば、 サーバーマシンに192.168.11.100というIPアドレスが降られている場合は

bind 127.0.0.1 192.168.11.100 #2019/9/19 訂正 127.0.0.1をとってしまうとlocalhostからの接続ができなくなります。

とすればこのIPアドレスが振られたNIC経由でのredisへの接続を受け付けるようになります。

もし複数のNICが搭載され、複数のIPが振られている状態で両方のネットワークから接続を受け付けたい場合は

bind 192.168.11.100 192.168.1.100

のようにスペース区切りにすると複数指定できます。

また、すべてのNIC経由での接続を受け付けたい場合は

bind 0.0.0.0

とします。

設定が終わったら、Linux系の場合は

sudo systemctl restart redis-server (あるいはredis)

とします。

mac OSなどでフォアグラウンドで起動している場合はいったんredisを停止させてから起動しなおします。

この状態で再度 redis-cli コマンドでリモートにつなげると

こんな感じでリモートからでも接続できるようになります。

・次の記事
redisを触ってみる 基本操作編

  • この記事いいね! (0)
著者:ym

Windows サンドボックス

先日ようやく Windows Update May 2019 Update をしたので、「Windows サンドボックス (sandbox)」という機能を使ってみました。

この機能は Windows OS上に、危ない環境をテストする為のOSで、このOSで実行する限りは、親の OS には影響が出ない環境です。

サンドボックスのウィンドウを閉じると、データは初期化されてしまいます。

インストールテストなど、環境を壊しかねない機能を事前にテストする際に良さそうです。私のHDDなPCでもどうにか、素早く(30秒程度)で起動してくれました。

再起動や、サインアウトすると、セッション切断されて初期化されるが、日本語にならないのは、どうにかならないのだろうか。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】「cordova-plugin-socket-tcp」プラグインでサーバーとの接続が失敗する

原因は完全に私のミスですが、再発防止の意味も込めてまとめ。
先日投稿した「【Cordova】TCPプロトコルを介してサーバーと通信するためのプラグイン「cordova-plugin-socket-tcp」」という記事で紹介したプラグイン「cordova-plugin-socket-tcp」でサーバーとの接続が一定時間後に何故か切れてしまう時の対処法です。

GitHub のページはこちら。

GitHub – kitolog/sockets-for-cordova: Cordova plugin for socket network communication
https://github.com/kitolog/sockets-for-cordova

 

発生していた現象は、メソッド .open() を使って、指定したサーバーに接続した際、一定時間が経過すると、onErroronClose ハンドラが呼ばれるという物でした。
なお、その際のエラーは「Read timed out」でした。
また、後輩君のアドバイスで、数秒間隔でデータを送り続ければ途切れないのでは?とのアドバイスも頂きましたが、実装しても意味はなかったです…。

で、こちらの対処法ですが、プラグインを入れ直すことで解決できました…!
プラグインインストール時に、ドキュメントに記載されているコマンドではなく、下記のコマンドを実行してしまったことが原因でした。

cordova plugin add https://github.com/kitolog/sockets-for-cordova.git

正しいコマンドはこちら。

cordova plugin add cz.blocshop.socketsforcordova

以前、他のプラグインで上記のようにドット区切りのプラグインを指定したところ、インストールに失敗したので、GitHub のURLを指定したんですよね。
で、今回も失敗するかもしれないと考えて、最初から URL を指定したところ、バグに遭遇しました…。
謎のアレンジを効かせた私が悪いということでした。
プラグインを正しいコマンドで入れ直したところ、問題なく動作するようになりました。

 

以上、Cordova のプラグイン「cordova-plugin-socket-tcp」が正常に動作しない時の対処法でした。
参考になれば幸いです。
あと、私のように変な修正はしないようにしてください。

  • この記事いいね! (0)
takahashi 著者:takahashi

Cygwinのバージョンを確認する方法

Unixライクな環境をWindows上で再現できるCygwinですが、使用しているとインストール済みのCygwinのバージョンが知りたくなる時があります。

Cygwinはインストーラーがパッケージマネージャを兼ねているような感じになっているので、Cygwinのインストーラーからインストール済みバージョンを確認することは可能です。

しかし、インストーラーをインストール後に破棄してしまった場合で、再度インストーラーをダウンロードできないような状況では困ることがあります。

実はCygwinではパッケージマネージャだけでなく、Cygwinターミナル上からもバージョンを確認することができます。

下記のコマンドを実行します。

cygcheck -c cygwin

すると下記のような形でバージョンが出力されます。

$ cygcheck -c cygwin
Cygwin Package Information
Package              Version        Status
cygwin               2.10.0-1       OK

cygcheckコマンドはインストールされたcygwinパッケージのバージョンなどを表示することができるコマンドなのですが、Cygwin本体もCygwinのパッケージとして扱われているので、このコマンドで情報が確認できるようになっているようです。

Cygwinのバージョンのチェックが必要な場合は参考にしてみてください。

  • この記事いいね! (0)
著者:杉浦

【Windows10】起動時に高頻度でブルースクリーンになる問題の対処法の一つ

 結論として、対処法の一つは高速スタートアップを切ることでした。切り方は以下の通りです。

アドレス:コントロール パネル\ハードウェアとサウンド\電源オプション\システム設定
UIを使った移動経路:コントロールパネル->ハードウェアとサウンド->電源オプション->電源ボタンの動作を選択する
移動した場所にある「高速スタートアップを有効にする(推奨)」のチェックを外す。
※チェックを外す前に「現在利用可能ではない設定を変更します」のメッセージをクリックする必要がある場合があります。


 これをするとPCが健康になる場合があります。勝手な想像ですが、高速スタートアップをするべきでないPCスペックであるにも関わらず高速スタートアップをしようとしていたのでしょう。
 以下、解決までの道筋です。
 今回起きていた問題は題にある通り、起動時に高頻度でブルースクリーンになる、というものでした。今回の問題の厄介な点はブルースクリーン時に表示されるエラーコードが多様だった点にありました。例えば、SYSTEM_THREAD_EXCEPTION_NOT_HANDLED、MEMORY_MANAGEMENT、BAD_POOL_CALLERです。このためエラーコードをググってピンポイントな解決を見つけることができませんでした。起きているエラーについて詳しく調べることでGoogle先生の提案する解決策を絞り込めます。エラーについて詳しく調べるにはWindowsのログを追うことが一つのやり方です。
 Windowsのログはコンピュータの管理のイベントビューアーから見ることができます。ここからエラー、警告、重大といった問題の起きそうなイベントのログを見ます。今回ならばとりあえず終了時の問題か、起動時の問題かの二択が想像でき、どちらの問題か調べようとしました。このログを見る限り、起動時に問題が発火、大炎上しています。

 これの中を読んでググってとしていくと起きていることがエラーコードのみよりもずっと深くわかります。今回は起点が常に高速スタートアップの失敗で、まさにそれが原因でした。(下図の様に高速スタートアップの失敗がいつも起きていた。そこから派生していくイベントのどこかしらで決定的な破綻が発生。)
 

 後は”高速スタートアップ”でググって予測で出てきた”高速スタートアップ 無効”で提案されたやり方を適用して処置完了です。
 処置後の経過をざっくり見るには信頼性モニター(コントロール パネル\システムとセキュリティ\セキュリティとメンテナンス\信頼性モニター)が便利です。以下の様に起きたイベントからPCの状態を評価、表示してくれます。処置後は回復に向かっており、一度も起動時のブルースクリーンは起きていません。

  • この記事いいね! (1)
asaba 著者:asaba

【android】intentの戻り値には、帰ってきた値に合わせて細かく切り分けて対応する

intentで何かの処理をした結果は、コールバックであるonActivityResultの引数として

返ってきます。この中のrequestCodeとresultCodeの内容に合わせて処理を分けていくのですが、

例えばカメラで撮った画像を受け取りたい場合は下記のようにかきます。

 


if(requestCode == RESULT_CAMERA && resultCode == RESULT_OK)

 

左辺がカメラモードに入った状態、右辺がカメラが正常に終了した状態。

この条件が二つ合った場合のみ処理に入っていきます。

ギャラリーの場合も同じように

 

<pre>if(requestCode == REQUEST_GALLERY && resultCode == RESULT_OK)</pre>

 

と書いていきます。requestCodeの判定だけでは縛りが甘く、リクエストした

結果が得られない時があります。

 

例えば、カメラモードに入って何も撮影せずに戻ろうとした時。

上のカメラ撮影処理において、条件がrequestCode == RESULT_CAMERAのみ

だった場合、本来ならば戻る=resultCode==RESULT_CANCELと決まっているのですが

条件が一つだけなので、カメラ撮影が成功したと判断されその下の処理へと

走ってしまいます。すると当然Uriが存在しないので何もない状態のimageViewを

返してしまう羽目になるのです。

 

自分の場合は条件がrequestCode == RESULT_CAMERAのみで、更に関数にvoidが

ついているにも関わらず分岐の中でreturnを使った処理を付けてそのままにしておいた

ためカメラモードで戻るを押した際にimageviewが消失する事故が起きました。

(恥ずべき間違いとは言えない)

この沼にはまると結構な時間を取られてしまうので注意したいですね。

 

onActivityResultで結果を受け取る際はresultCodeの結果もチェックして

処理を書いていきましょう。

 

下記テンプレコード

<pre>@Override
protected void onActivityResult(int requestCode,
                                int resultCode, Intent intent) {
    
    if (requestCode == RESULT_CAMERA && resultCode == RESULT_OK) {
      //カメラの処理</pre>
<pre>      } else if(requestCode == REQUEST_GALLERY && resultCode == RESULT_OK){
   //ギャラリーの処理</pre>
<pre>        } else if(resultCode == RESULT_CANCELED){
    ※カメラ・ギャラリーモードがキャンセルされた時(重要)
        }
      }
    }
</pre>

 

 

  • この記事いいね! (0)
著者:杉浦

【Git】git-submoduleことはじめ

 Git自体のパッケージマネージャの様な機能としてgit-submoduleがあります。git-submoduleはgitコマンドの一つでgitを導入すれば勝手にくっついてきます。
 Git – git-submodule Documentation
 git submoduleはGitリポジトリの中にGitリポジトリをクローンする機能です。これを使えばバージョン固定や定期的なコピペから解放されます。ある一つのDocker設定を用いたり、開発プロジェクトで用いない言語のライブラリと連携したりする時に特に便利です。

 基本のコマンドは二つ覚えておけば大丈夫です。git submodule add [cloneする時とかのURL] [保存先ディレクトリ]でリポジトリを追加、git submodule updateでリポジトリをまとめて更新、この二つだけです。
 Gitリポジトリの中にGitリポジトリがあると言ってもいいくらいなのでGitコマンドの対応が大体用意されています。ブランチの切り替えで安定版、開発版の切り替えも楽々です。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】「Peripheral null not found」エラーの対処法

今日遭遇したエラーの対処法についてです。
記事でまとめるほどでもないかな…とも思ったのですが、念のため。

なお、こちらのエラーは Cordova のプラグイン「cordova-plugin-ble-central」の stopNotification() メソッド実行時に発生しました。
こちらのプラグインの GitHub のページは下記からご確認ください。

GitHub – don/cordova-plugin-ble-central: Bluetooth Low Energy (BLE) Central plugin for Apache Cordova (aka PhoneGap)
https://github.com/don/cordova-plugin-ble-central

 

さて、原因ですが、大体このエラーメッセージの次の行に詳細が書かれているので、こちらを確認します。
私の場合は、メソッドの引数に指定する device_idservice_uuidcharacteristic_uuid の値が正しく指定できていなかったために発生していました。
引数に指定する値の取得を修正し、正しい値を代入して実行したところ、問題なく動作しました。

なお、エラーメッセージを検索した際にヒットした記事はこちら。

Android BLE connection crashes after 15-25 seconds · Issue #129 · don/cordova-plugin-ble-central · GitHub
https://github.com/don/cordova-plugin-ble-central/issues/129#issuecomment-210252678

上記のリンク先の投稿にエラーメッセージのログが載っていますが、こちらでも2行目にエラーの詳細が表示されているのが分かるかと思います。

 

以上、「Peripheral null not found」エラーの対処法でした。
最初、エラーメッセージの意味が分からなかったので、とりあえず検索にかけてしまいましたが、エラーメッセージを冷静に読み直せば別に難しくもなんともなかったですね。
ご参考になれば幸いです。

  • この記事いいね! (0)