Androidのメモとか

ポキオの日記です。今日も遅延してない。

Electronでアプリを作るときにハマったメモ

メモ。

electron tips

Electronはじめました

前回からElectronアプリを書き始めたんですが、何箇所かハマったのでメモ。

relativelayout.hatenablog.com

Zoomを無効にしたい

フツーにアプリをElectronで作ると、タッチパッドのピンチイン・ピンチアウトが効いてしまって、なんかアプリっぽくありません。

Zoomを無効化するには、webFrameを使うといいらしく、こんな関数を書いてみました。

function disableZoom() {
    var webFrame = require('electron').webFrame;
    webFrame.setVisualZoomLevelLimits(1, 1);
}

これをHTML上で実行するだけ。意外と簡単。

npm installしたモジュールがElectronアプリから呼び出せない

requireしても、モジュールが無いよって怒られる件。結局、npm installするときに--saveオプションを有効にしないとrequire出来ないっぽい。--save-devではだめっぽい。

それでもElectronでjQueryがundefinedになる

もう意味がわからない。

<script src="./node_modules/jquery/dist/jquery.min.js"></script>

こういう記述の代わりに、これを書けば解決できる。理由は知らない。

<script>
    window.jQuery = window.$ = require('./node_modules/jquery/dist/jquery.min.js');
</script>

stackoverflow.com

クリップボードの読み書きがしたい

こんな感じで出来ました。

var clipboard = require('electron').clipboard;
var hoge = clipboard.readText(); // クリップボードの値を読む
clipboard.writeText("fuga"); // クリップボードに値を書き込む

みなさんも、よいElectronライフを。

ElectronでmacOSアプリをチョッパヤで書いてみる

意外と簡単?

electron アプリ 開発

Electronとは?

これ。

electronjs.org

要はWeb技術でクロスプラットフォームアプリ開発が出来てしまう、すごいやつです。モバイルアプリではPhonegap・Cordovaなどが有名ですが、そのDesktop版といったところでしょうか。いままで書いてきたWebの資産が活かせそうなので、今回はmacOS向けに簡単なアプリを書いてみようと思います。

まずは準備

nodeやnpmが使える前提です。

まずは適当なところにフォルダを掘っておきます。

mkdir electron-test
cd electron-test

そのフォルダ直下で初期化して、electronelectron-packagerをインストール。 これで、Electronを使ってアプリを動作させる環境と、macOS向けにアプリという単位でバイナリを吐ける環境が整いました。

npm init -y
npm install electron --save-dev
npm install electron-packager --save-dev

いろんなサイトにかかれているお作法に則って、srcフォルダを掘ります。実際のアプリのコードはsrc内に書いていきます。

mkdir src

lsするとこんな感じ。

ls
node_modules        package.json
package-lock.json   src

おいおいElectronでアプリを実行したり、アプリとして配布できる形に書き出すときに必要なコマンドがありますが、それをpackage.jsonに上記のように書き込んでおくと、npm run startnpm run build-macOSのように簡単にコマンドを呼ぶことができるようになり便利です。

  "scripts": {
    "start": "electron ./src",
    "build-macOS": "electron-packager ./src electron-test --platform=darwin --arch=x64 --overwrite",
    "build-windows": "electron-packager ./src electron-test --platform=win32 --arch=x64 --overwrite"
  }

アプリの中身を書いていく

先述のとおり、src内でコードを書いていきます。そして、src直下でも初期化します。

cd src
npm init -y

上記コマンドで生成されたpackage.jsonを少し変更します。Electronではmain.jsが最初に読まれ、アプリのエントリポイントもmain.jsになるので、下記のようにmainを変更します。

  "main": "main.js",

そして、そのmain.jsを書いていきます。今回は、このサイトのコピペをさせていただきます・・・。

'use strict';

var electron = require('electron');
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;

var mainWindow = null;

app.on('window-all-closed', function () {
    if (process.platform != 'darwin')
        app.quit();
});

app.on('ready', function () {
    mainWindow = new BrowserWindow({ width: 800, height: 600 });
    mainWindow.loadURL('file://' + __dirname + '/index.html');

    mainWindow.on('closed', function () {
        mainWindow = null;
    });
});

main.jsではアプリのウィンドウを開きつつindex.htmlを開いて表示させるコードになっています。では、つぎにindex.htmlを作ります。こちらはテキトーにHello, Electron!とだけ書かれたファイルを準備します。

これで一旦完了。

いざ実行

srcではなく、一つ上の階層で、下記のコマンドを実行します。

npm run start

すると、こんなウィンドウが表示されます。

electron アプリ 開発

とりあえず動きました!同じようにnpm run build-macOSをすると、.appファイルが生成出来ます。

というわけで

今回は内容はしょぼいアプリですが、index.htmlをゴリゴリ書いていけばいろいろなアプリが簡単に作れそうです!お疲れ様でした!

Appendix

30分で出来る、JavaScript (Electron) でデスクトップアプリを作って配布するまで - Qiita

勉強メモ/npmの使い方(node.js=v0.11.16, npm=2.3.0, 2015-03時点) - Qiita

Google HomeをNode-REDからgoogle-home-notifierを使って喋らせる

SAY YES。

前回はJavaScriptからGoogle Homeを喋らせました

relativelayout.hatenablog.com

JSでできるんならNode-REDでもイケるんじゃね?って思ってやってみた。

Functionノードではrequireできない

この前、こんなコードを書きました。

const googlehome = require('google-home-notifier')
const language = 'ja';

googlehome.device('Google Home Mini', language);

googlehome.notify('こんにちは!ポキオです!', function(res) {
  console.log(res);
});

この前のコードをFunctionノードに書けばイイんじゃね?そう思って、やってみると、

"ReferenceError: require is not defined (line 2, col 20)"

こんな感じで、怒られてしまいます。Functionノードではrequireが使えないようです。

requireが必要なものは予めrequireする

このページを参考にさせていただきました。

グローバルコンテクストはNode-REDの起動時にオブジェクトと共に前もって生成しておくこともできます。メインのsettings.jsの中のfunctionGlobalContextプロパティの中で定義することでそのように動作します。

とどのつまりが、~/.node-red/settings.jsで予めrequireして、それをグローバル変数のように使えば良さそうです。

functionGlobalContext: {
    googlehomenotifier:require('google-home-notifier'),
    (省略)
},

こんな感じでfunctionGlobalContextの部分で、google-home-notifierを取り込んでおきます。Functionノードでは、この変数を呼び出せばいいので、

const googlehome = context.global.googlehomenotifier;
const language = 'ja';

googlehome.device('Google Home Mini', language);

googlehome.notify('こんにちは!ポキオです!', function(res) {
  console.log(res);
});

context.global.googlehomenotifierで呼び出せばOKです。

せっかくなので喋らせるフレーズを可変にする

せっかくなので。喋るフレーズをmsg.payloadを読み込むようにして、別のNodeから与えられるようにしました。

const googlehome = context.global.googlehomenotifier;
const language = 'ja';

googlehome.device('Google Home Mini', language);

googlehome.notify(msg.payload, function(res) {
  console.log(res);
});

return msg;

Nodeを繋いでいきます

今回は、Injectノードでトリガーを与えてみます。また、Injectノードを複数用意して、それぞれのmsg.payloadを変えています。

Node-RED Google Home google-home-notifier

ちゃんと喋りましたー。ここまで来たら、トリガーを自動化したり、喋る文言を動的に作り変えたり、なんでもできそうですね!

育児と鬼とGoogle Home

多分、賛否両論あるので、グチグチ言う人は見ないで下さい。

育児 鬼 Google Home

tl;dr

Google Homeをつかって、子供を優しく脅す仕組みを作りました。

子供①と子供②が熱を出しました

保育園の決まりで、熱が37度以上あると登園出来ないし、登園したが途中で熱が37度以上出ると、保育園から呼び出しをされて、子供を連れて帰らなければならないわけなのですが。先日、うちの子*2が熱を出して、結構長引いていたので、会社を休んで、親子三人でずっと家に居ました。

大人であれば、熱を出したらぐったりして、何もする気がなくなるというのが相場なのですが、子供は熱を出しても元気という仕様バグのような挙動をするので困るわけです。なので、先日もギャーギャー騒いだりすごかったわけです。親としては、少し寝てくれれば、早く良くなるし、こっちは色んな仕事が捗るからうれしいんだけどなぁとか思ってました。かと言って、寝かそうとしても言うことを聞かなかったりするので困るわけです。

言うことを聞かない子供へのモダンなアプローチ

最近は、「おにから電話」というアプリがあります。

育児 鬼 Google Home

www.onikara-denwa.com

アプリで、あたかも鬼から電話がかかってきたかのように振る舞い、通話を開始するとアプリが鬼っぽい声で喋りだし、「言うことを聞くように」「早く寝るように」と子供を脅してくれる仕様になっています。で、意外と効果があるんです。

これ、もしかしたら、適当な言葉をText To SpeechでGoogle Homeで喋らせて、それで子供が言うことを聞いてくれたら最高じゃね?って思ったわけです。

とりあえず試作品を作る

google-home-notifierでGoogle Homeを喋らせることが最近できたので、それを使って早く寝るような言葉を喋らせて見ようと思います。

育児 鬼 Google Home

お試し実装なのでシステムは複雑ですが、寝かせたいと思った時にMacBook AirからRaspberry Pi上でスクリプト実行させGoogle Homeを喋らせます。スクリプトはこちら。

const googlehome = require('google-home-notifier')
const language = 'ja';

googlehome.device('Google-Home-Mini', language);

googlehome.notify('早く寝ないと、鬼が来ていたずらしちゃうよ。', function(res) {
  console.log(res);
});

こんな感じで実行します。

node oni.js 

スクリプトのファイル名をoni.jsとかにしておくとかっこいいですよね。

使ってみた

結果から言うと、ちょっと微妙だったけど、布団に直行してた。

  • 声がお姉さん(鬼の声じゃない)
  • トリガーがいまいち(いい感じに自動化、もしくはリモコン化したい)
  • 喋りかける内容がハードコード(自由に切り替えられるようにしたい)
  • こどもがGoogle Homeから遠いところにいると、声が聞こえない(これはどうしようもないのか・・・?)

色々課題は有るけど、ちょっと使えそう。ちょっとブラッシュアップしていこうと思います。

Raspberry Piにgoogle-home-notifierを導入するときのメモ

google-home-notifier on Raspberry Pi and nougat

前回はgoogle-home-notifierを導入しました。

relativelayout.hatenablog.com

ハマったポイントを書いておきます

要はREADMEをちゃんと読めっていう話なんですが。

git-core libnss-mdns libavahi-compat-libdnssd-dev はインストールすること

よしなに、

sudo apt-get update

してから、

sudo apt-get install git-core libnss-mdns libavahi-compat-libdnssd-dev

をしましょう。私の環境の場合、すでにこれらが入っていたので動いていたようです。

mdnsを使う場合はファイルを書き換える

ここに書いてあるとおり、node_modules/mdns/lib/browser.jsを書き換える必要があります。

Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
, rst.makeAddressesUnique()
];

このような記載を、

Browser.defaultResolverSequence = [
  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
, rst.makeAddressesUnique()
];

と書き換えて上げる必要があります。{families:[4]}を追加するだけです。

これにより、

googlehome.device('Google Home Mini', language);
googlehome.ip('192.168.xxx.xxx');

と書いていた部分の、googlehome.ip('192.168.xxx.xxx');の部分を取り除いても正しくワークします。

WARNINGが出るけど、放っておく

これでいいのかな・・・。

*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>

確かにきになるんですが、正しくワークしてるので、気にしないでおきます。

google-home-notifierをRaspberry PiにインストールしてGoogle Home Miniを喋らせる(追記)

今更ですが。

google home mini with google-home-notifier on Raspberry Pi

Google Homeをつかってみます

ちょっと前に買ったものの、通電したまま部屋に放置していました。そろそろ触ってあげないとかわいそうなので、触ってあげます。

[asin:B01N10FAFU:detail]

Google Homeの制御には、皆さんおなじみのgoogle-home-notifierを使っていきます。

github.com

これをGoogle Homeと同一ネットワーク上にいるRaspberry Pi上で動かしてみます。

準備

jsとかnodeとかnpmとかでゴニョゴニョするということなので、とりあえずnodeを最新にしていきます。面倒なので、update-nodejs-and-noderedというコマンドでそれなりに新し目の環境にします。

$ update-nodejs-and-nodered 

Node-REDも新しくなって、一石二鳥ですね。

Fetching Node-RED update.

(省略)

This can take 20-30 minutes on the slower Pi versions - please wait.

  Stop Node-RED                       ✔
  Remove old version of Node-RED      ✔
  Remove old version of Node.js       ✔
  Install Node.js for Armv6           ✔   Node v8.11.2   Npm 5.6.0
  Clean npm cache                     ✔
  Install Node-RED core               ✔   0.18.5 
  Move global nodes to local          -
  Install extra Pi nodes              -
  Npm rebuild existing nodes          ✔
  Add menu shortcut                   ✔
  Update systemd script               ✔
  Update update script                ✔

(省略)

はい、よしなに新しくなりました。

$ npm install google-home-notifier

で、google-home-notifierをインストールします。これで完了。

お喋りするよ!

ここを参考に、ざっくりJSでプログラムを書いてみます。

const googlehome = require('google-home-notifier')
const language = 'ja';

googlehome.device('Google Home Mini', language);
googlehome.ip('192.168.xxx.xxx');

googlehome.notify('こんにちは!ポキオです!', function(res) {
  console.log(res);
});

後述しますが、Bonjourが上手くワークしてないようで、機器名からアドレスを解決出来てなかったようなので、アドレスを直打ちしています。

$ node pokio.js

で、こんな感じでJSを実行します。

*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
Device notified

Bonjour関係で怒られますが、Device notifiedと表示された後に、Google Homeから効果音が鳴り、「こんにちは!ポキオです!」と喋ります。若干ポキオのイントネーションがアレですが、とりあえず喋りました!


msdnが効かなかったのは、この手順を踏んでいなかったためでした

その他、気をつける点をまとめました。

relativelayout.hatenablog.com

Android Things 1.0をRaspberry Piでサクッと動かしてみる

ついに1.0。

android things 1.0 raspberry pi

Android Things 1.0

developer.android.com

jp.techcrunch.com

I/Oに先立って、Android Thingsが正式リリースされました。APIがガラッと変わったりSupported Devicesが増えたり、色々変わっていますが、相変わらずRaspberry Pi 3Bで動作可能っぽいので、とりあえずチョッパヤで動作環境を準備して動かしてみます。

tl;dr

  • 何処かにイメージが置いてあって、それをDLしてSDに焼けばいいみたいな方式ではなくなった
  • コンソールにアクセスして、そこでAndroid Thingsのイメージを作成する必要がある
  • RPi 3B+純正タッチディスプレイで動作確認ができた
  • ディスプレイが上下さかさまで表示されいるのでどうにか対応したい

動作環境

この環境をそのまま使います。

relativelayout.hatenablog.com

  • RPi 3B
  • オフィシャル タッチディスプレイ
  • 専用ケース
  • Micro SD (8GB)

RPi用のイメージをダウンロードするまで

まずはコンソールにアクセス。

https://partner.android.com/things/console/

android things 1.0 raspberry pi

もろもろのAgreementsにAgreeしていきます。

android things 1.0 raspberry pi

まず、なんでもいいのでProductを登録します。SOM TypeRaspberry Pi 3を選択しておきます。

android things 1.0 raspberry pi

Productを登録できました。右上のNEWを押して、Start from scratchを選択して、Buildの設定を新規に作成します。このBuildがゆくゆくRPi用のイメージになっていきます。

android things 1.0 raspberry pi

まずはBuildの名前。テキトーです。

android things 1.0 raspberry pi

次にAndroid Thingsのバージョンを選択。現状1.0しか選択できません。

android things 1.0 raspberry pi

android things 1.0 raspberry pi

android things 1.0 raspberry pi

App、Resources、Hardware Configurationは特に作ってないので、何も選択せずにNEXTをポチポチしていきます。

android things 1.0 raspberry pi

パーティションサイズもそのまま進めます。

android things 1.0 raspberry pi

これで、Buildの設定が完了しました。コンソール上の表示では、Buildの準備が始まります。

android things 1.0 raspberry pi

準備が終わると、Release向けとDebug向けのイメージがダウンロードが可能になります。

android things 1.0 raspberry pi

今回はDebug向けのイメージをダウンロードしてみます。ダウンロードをすると、イメージのダウンロードに向けて準備が始まって、しばらくして実際のイメージ(zipファイル)がダウンロードされます。

RPi用のイメージをSDに焼く

先程のZipファイルを解凍すると、imgファイルが出現します。

android things 1.0 raspberry pi

zipファイルは300MB程度だったのに、imgファイルは4GB以上・・・。まぁいいです。

android things 1.0 raspberry pi

本家Raspbianと同様に、このimgファイルをEtcherを使ってSDカードに書き込んでいきます。

いざ起動

先程作ったSDカードをRaspberry Piに挿して起動。

android things 1.0 raspberry pi

スプラッシュ画面がAndroid Thingsですね。上下さかさまで表示されています。

android things 1.0 raspberry pi

起動完了したっぽい。色々な設定やバージョン確認ができる画面が表示されました。

android things 1.0 raspberry pi

Wi-Fiの設定もGUI上で可能で、文字入力もおなじみのキーボードで入力可能です。タッチパネルもちゃんとワークしていました。

とりあえず、起動完了しました。お疲れ様でした。

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。