2015年6月20日土曜日

[Raspberry Pi]Demo programs

Raspberry Pi(Raspbian)のサンプルプログラムの話です。

DEMO PROPGRAMS
に詳しく書いてあります。

$ cd /opt/vc/src/hello_pi
$ ./rebuild.sh
$ cd hello_tiger
$ ./hello_tiger

なかなかの迫力ですよ!



2015年6月14日日曜日

[Raspberry Pi]おすすめの本

Raspberry Piでおすすめの本をご紹介いたします。


こんな人におすすめです。
・プログラミングの経験はあるけれども、40本のピンをどう使えばよいのかわからずにもてあましていて、LEDをチカチカさせてみたい人。プログラミングの知識は入門書程度の内容で大丈夫です。その他本書ではタクトスイッチ、温度センサー、モーター、WebIOPiが取り上げられています。
 ・Python (PiはPythonに由来するそうです)
 ・Ruby
 ・Java
 ・C / C++
 ・Scratch 等
・Raspberry Piに興味があってはじめてみようとおもっているけれども、まわりにやっている人がいなくて何を買いそろえればよいのかわからない人。
・予備知識はないけどとにかくRaspberry Piをはじめてみようというやる気のある人。プログラムはダウンロードができるのではじめはそれをそのまま使うことでよいとおもいます。Pythonはドットインストール様で学ぶことができます。
・サポートページがありまして、最新内容を反映してくださっている点もおすすめポイントです。

楽しみましょう!


[android]Android Design Support Libraryをつかってみる

Android Design Support Libraryはこちらで紹介されています。

日本語では「Android Design Support Libraryを使う」で紹介されています。
サンプルコードも紹介いただいています。
ありがとうございます。

自分が作っているアプリにFloatingActionButtonを組み込もうとおもってレイアウトに、追加してみたのですが実行しようとするとレイアウトのインフレートで失敗しました。

こんなエラー内容でした。

android.view.InflateException: Binary XML file line #19: Error inflating class android.support.design.widget.FloatingActionButton
(略)
Caused by: android.view.InflateException: Binary XML file line #19: Error inflating class android.support.design.widget.FloatingActionButton

インフレートに失敗した原因は下記のようです。
* Activityはandroid.support.v7.app.AppCompatActivityを継承していないといけないようです。Support Libraryですからね。
* (言わずもがなかもしれませんが……)ということで、マニフェストで指定するandroid:themeのparentはTheme.AppCompat.Light.DarkActionBar等にしないといけないようです。


上記とは関係ありませんが、Android Devlopersみてて気づいたのでついでに書いておきます。Data Bindingについて書いておきます。
レイアウトのxmlにデータクラス名を書いておくとたとえばTextViewなんかで、下記みたいに書けるようになるそうです。

<TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"/>



Google I/O 2015 - What's new in Androidで紹介されていたData Bindingのガイドがありました。こういう書き方が今後の主流になるんじゃなかろうかと個人的にはおもいます。


2015年6月12日金曜日

[Raspbery Pi]天気予報をしゃべる目覚まし時計

Raspberry Piで天気予報をしゃべる目覚まし時計を作ってみました。


天気予報はWeather Hacks様で調べることにしました。
音声ファイルはdocomo Developer support様の音声合成で作ります。
Open JTalkを使う方法もあるようです。詳しくは第20回「ラズベリーパイで手作り目覚まし時計!(2)音声アラーム編」。とても詳しく書かれています。

Rubyで作りました。
$ ruby -v
ruby 2.0.0p645 (2015-04-13 revision 50299) [armv7l-linux-eabihf]

ソースコードはこんな感じです。
docomo Developer supportの音声合成API Keyは取得したものを記載してください。

あとはこれを$ crontab -e とかで
45 6 * * * <command>
みたいなのを書いておけば6:45に天気予報をしゃべってくれます。
cronも第19回「ラズベリーパイで手作り目覚まし時計!ストップボタン編」の説明をご紹介しておきます。
参考にさせていただきました。ありがとうございます。


require 'open-uri'
require 'json'
require 'uri'

# http://weather.livedoor.com/weather_hacks/
class Weather
  attr_accessor :id

  BASE_URL = 'http://weather.livedoor.com/forecast/webservice/json/v1?city='

  def initialize(id)
    @id = id
  end

  def get
    json = nil
    open("#{BASE_URL}#{id}") do |f|
      json = f.inject('') do |memo, line|
        memo + line
      end
    end
    parse(json)
  end

  private
  def parse(json_text)
    json = JSON.parse(json_text)
    "今日の" + json['location']['prefecture'] + json['location']['city'] + "の天気は" + json['forecasts'][0]['telop'] + 'です'
  end
end

# https://dev.smt.docomo.ne.jp/
class TextToFile
  attr_accessor :msg, :speaker, :file_path

  # https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=text_to_speech&p_name=api_hoya#tag01
  API_KEY = 'Your API Key'
  URL = "https://api.apigw.smt.docomo.ne.jp/voiceText/v1/textToSpeech?APIKEY=#{API_KEY}"

  def initialize(opts)
    @msg = opts[:msg]
    @speaker = opts[:speaker]
    @speaker ||= %w(show haruka hikari takeru santa bear).sample(1)[0]
    @file_path = opts[:file_path]
  end

  def to_file
    uri = URI.parse(URL)
    https = Net::HTTP.new(uri.host, uri.port)

    https.use_ssl = true
    req = Net::HTTP::Post.new(uri.request_uri)

    req["Content-Type"] = "application/x-www-form-urlencoded"
    req.body = "text=#{URI.encode(msg)}&speaker=#{speaker}&speed=50&format=wav"

    res = https.request(req)

    File.open(file_path, 'wb') do |file|
      file.write(res.body)
    end
  end
end

# 調べたい地域のIDを指定してください。
# http://weather.livedoor.com/forecast/rss/primary_area.xml
w = Weather.new('130010')
TextToFile.new(msg: w.get, speaker: 'haruka', file_path: 'speech.wav').to_file

`aplay speech.wav`




[Raspberry Pi]無線LANアダプターでつなぐ

簡単でした。
1. I-O DATA WN-G150UをUSBポートに挿して電源投入
2. この時点で無線LANアダプターが青くピカピカ光っています
3. 右上のインターネットのアイコンをクリックするとSSIDが表示されるのでパスフレーズ等入力してください(お使いのWi-Fiルートの裏とかに書いてあるあれです)


以前は設定ファイルみたいなのを編集する必要があったようですが、挿すだけで使えてしまいました。

【環境】
* Raspberry Pi 2 Model B
* OS Raspbian: NOOBS 1.4.1(2015-05-11)でインストールしたやつです。
Linux raspberrypi 3.18.14-v7+ #793 SMP PREEMPT Sat May 30 14:04:35 BST 2015 armv7l GNU/Linux

バージョンの調べ方はこちらを参考にさせていただきました。
ありがとうございます。
$ uname -a

2015年6月9日火曜日

[android]ActiveNotification

Android M Developer Previewのサンプルを読んでみます。
ActiveNotification
・Activityが2つ、Fragmentが1つのサンプルです。
 ・ActivityはActiveNotificationActivityがMainActivityを継承しています。
  ManifestにはActiveNotificationActivityだけが書かれていますので、このActiveNotificationActivityだけが使われています。
・起動すると、ActiveNotificationFragmentインスタンスをFragmentTransaction#replaceしています
・ActiveNotificationFragmentは画面やボタンの初期化をしています
・「ADD A NOTIFICATION」ボタンを押すと、ActiveNotificationFragment#addNotificationAndReadNumber()が呼ばれて、NotificationManager#notifyでNotificationが画面上部に追加されます
・このNotificationは消えるときに、Intent("com.example.android.activenotifications.delete")がBroadcastされます
・このIntentはActiveNotificationActivity#onResumeで登録されたBroadcastReceiverで受け取ります。
・BroadcastReceiverがIntentを受け取ると、ActiveNotificationFragment #updateNumberOfNotificationsを呼び出して、Notification数の更新をしています。
・このサンプルのポイントです。android.app.NotificationManager#getActiveNotifications()というAPIがMから追加されています。このAPIで現在表示されているNotificationの数を数えられます!




2015年6月8日月曜日

[Raspberry Pi]イヤホンジャックに差し込んでも音が鳴らない そんなときは

画面右上のスピーカーのアイコンを右クリックして、HDMIをAnalogに変更してみてください。

Raspberry Pi 2 Model B
OS: RASPBIAN Release date:2015-05-05





2015年6月7日日曜日

[android]Fingerprint Dialog

Android M Developer Previewの話です。
Fingerprint Dialog Sample を読んでみます。

・このサンプルはInjectを使って変数の初期化をしています
・com.example.android.fingerprintdialog.MainActivity#onCreateではまず、requestPermissions(new String[]{Manifest.permission.USE_FINGERPRINT}, 0);を使って指紋認証パーミッションの許可を取得しています
・com.example.android.fingerprintdialog.MainActivity#onRequestPermissionsResult
では指紋認証の許可が取れていた場合、android.app.KeyguardManager#isKeyguardSecureで設定がされているかどうかをチェックしています。設定されていなければ「"Secure lock screen hasn't set up.\nGo to 'Settings -> Security -> Fingerprint' to set up a fingerprint"」をToast表示して終了です。
・まず、Settings -> Security -> Fingerprintで設定をしています。指示通り進めていくと、指紋センサーに触るように言われるのでエミュレータの場合は、「$ adb -e emu finger touch <finger_id>」で指紋センサーにさわったことにします。具体的には、「$ adb -e emu finger touch 1234」みたいな感じです。
・再びFingerprint アプリを起動します
・PURCHASEボタンを押すと下図のようなダイアログが表示されるので、指紋センサーに触ります。エミュレータの場合は「$ adb -e emu finger touch 1234」みたいな感じです。
 ・ダイアログはcom.example.android.fingerprintdialog.FingerprintAuthenticationDialogFragmentです
 ・com.example.android.fingerprintdialog.FingerprintUiHelperで指紋認証のコールバックを受け取っています
 ・指紋認証の成功コールバックは、com.example.android.fingerprintdialog.FingerprintUiHelper#onAuthenticationSucceededです。
 ・com.example.android.fingerprintdialog.FingerprintAuthenticationDialogFragment#onAuthenticated -> com.example.android.fingerprintdialog.MainActivity#onPurchased -> com.example.android.fingerprintdialog.MainActivity#tryEncryptcom.example.android.fingerprintdialog.MainActivity#tryEncrypt へと連鎖します。私のエミュレータでは、この最後のtryEncryptメソッドで例外発生のルートへ突入します。そもそもこのタイミングでjavax.crypto.Cipher#doFinal(byte[])をしている理由がいまいちよくわからないです。
・指紋認証が使えないときの代替手段として、パスワード認証が用意されています。こちらはサンプルですので何を入力しても成功となっています。
・指紋認証関係のAPIをメモしておきます。
 ・android.app.Activity#requestPermissions : 指紋認証のパーミッションを要求します
 ・android.app.Activity#onRequestPermissionsResult: 指紋認証のパーミッションの結果がコールバックされます
 ・android.hardware.fingerprint.FingerprintManager#isHardwareDetected : 指紋認証のセンサーがあるかどうか
 ・android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints : 指紋が登録されているかどうか
 ・android.hardware.fingerprint.FingerprintManager#authenticate(FingerprintManager.CryptoObject crypto, CancellationSignal cancel, FingerprintManager.AuthenticationCallback callback, int flags) で指紋センサーからの入力をコールバックしてもらうオブジェクトを登録しておきます
・FingerprintManager.AuthenticationCallbackはabstractクラスで4つのコールバックがあります。指紋認証に成功したときのコールバックは、onAuthenticationSucceededです。








2015年6月4日木曜日

[android]Auto Backup

Android M developer Previewの話です。
詳細はここです。
・Android M developer Previewでアプリを動かすと、
・コードに一切手を加えることなく自動的にアプリのデータをクラウドにバックアップしてくれます。アプリの再インストールやデバイスの変更で自動的にリストアしてくれます。
 ・拙著『読書日記』で試してみたところ、本当にバックアップができました。何も手を加えておりません。
 ・テストするには
  $ adb shell bmgr run
  $ adb shell bmgr fullbackup <PACKAGE>
   とでもやって、アプリをアンインストール → インストールするとデータが復元されます。
・M developer Previewの期間はアプリ毎に25MBの領域が用意されているそうです。ユーザのGoogle Driveの領域は消費するのではないそうです。すばらしい!
・24時間ごとにデバイスがアイドルでWiFiに接続しているときにバックアップデータをクラウドへ送信するそうです。もちろん暗号化されて保存されるそうです。
・Auto Backupしないデータはありまして次のようなものです。
 ・getCacheDir()やgetCodeCacheDir()によって参照されるディレクトリ内のデータ
 ・外部ストレージのデータ
 ・getNoBackupFilesDir()によって参照されるディレクトリ内のデータ
・どれをバックアップして、どれをバックアップしないかのルールをアプリ独自に定めることもできます。android:fullBackupContent="@xml/mybackupscheme"みたいな感じの記述をmanifestに書いて、res/xml/mybackupscheme.xmlに定義するそうです。詳細はここを参照してください。
・いやいや、Auto Backupなんてしてもらわなくて結構ですよ、したくないんですよというアプリの場合は、android:allowBackup="false"をマニフェストに書いておけばよいそうです。
・サンプルはandroid-AutoBackupForAppsです。
 ・おもにAuto Backupの対象外とするファイルの定義の仕方が示されています。
 getNoBackupFilesDir()とxmlの書き方がメインです。
 というのもAuto Backupは本当に何もしないと自動的にバックアップ対象にしてくれますので。
 ・MainActivityはsetContentView(R.layout.activity_main);しているだけです。
 ・R.layout.activity_mainにMainActivityFragmentが記述されています。ということで、MainActivityFragment が表示されます。
 ・MainActivityFragmentは各保存場所(Internal, External, getNoBackupFilesDir())に格納されているファイルの一覧を表示します。
 ・MainActivityFragment -> AddFileActivity はオプションメニューで遷移します。
 ・AddFileActivity へ飛ぶとファイル名、ファイルサイズ、保存場所(Internal, External, getNoBackupFilesDir())を指定してファイルの保存ができるようです。
 ・Application/src/main/res/xml/backup.xml にAuto Backupを除外するxmlの書き方のサンプルが示されています。おそらくJavaのサンプルコードとの関連は何もない感じです。Javaコードの方にSharedPreferencesやデータベースの話などでてきておりませんが、xmlでは<exclude domain="sharedpref" path="user_credentials"/>や<exclude domain="database" path="local_secrets.db"/>がサンプルで書かれています。



2015年6月2日火曜日

[android]Confirm Credential

Confirm Credential を読んでみます。
Android M Developer Previewのサンプルの一つです。

ここに概要が書いてありまして、直近のアンロック操作を自前のアプリでも使えるようにしてくれるもののようです。これによりアプリ専用のパスワードをユーザが覚える必要はないし、開発者も自前で認証処理を書かなくてよくなるシロモノらしいです。

・Activity1個、レイアウト1個のシンプルなサンプルです。
・android.app.KeyguardManagerが2箇所で使われています。
 ・ひとつはonCreate内でKeyguardManager#isKeyguardSecureです。これがfalseの場合は"Go to 'Settings -> Security -> Screenlock' to set up a lock screen"「設定に行って、ロックスクリーンの設定をしてね」というToastを出してこのアプリは何もしていません
 ・もうひとつは認証画面の起動Intentを作ってくれるみたいです。
KeyguardManager#createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description)でIntentがかえってくるのでstartActivityForResultしています。結果はもちろんonActivityResultで、認証が通った場合にはもちろんRESULT_OKです。
・onCreateの中では、createKey()というprivateメソッドで「Creates a symmetric key in the Android Key Store 」を作っています。java.security.KeyStore、javax.crypto.KeyGeneratorというクラスのインスタンスを使っています。
・Purchaseボタンが押されたときは、tryEncriptというprivateメソッドで、KeyStore、SecretKey、Chipherクラスのインスタンスを使っています。
・createKey()、tryEncript()の中身は正直よくわかりませんがそういうものなのでしょう!



2015年6月1日月曜日

[android]Runtime Permissions

Runtime Permissionsは次期android M(8月?, 9月くらい?)で追加される機能です。
ここに詳しく書いてあります。
自分の理解した範囲で書きます。
あくまでも現時点のM Developer Previewでの話です。
・これまではインストール時にパーミッションの許可をユーザに委ねていた
・android Mではパーミッションが必要になったタイミングでユーザに許可をもとめるようにする
・ユーザーは設定画面から許可したパーミッションの取り消しをいつでもおこなえる
・targetSdkVersionをMにしなければ旧来通りのインストール時にすべてのパーミッションを求めるモデルになる。ただしこの場合でもユーザーは設定画面からパーミッションの取り消しを行える。パーミッションの取り消しが行われると、パーミッションが必要なAPIを呼び出したときに例外は起きないが空データが返る等の動作になる(やっぱりこのRuntime Pemissionsの対応は必須のようです)
・すべてのPermissionについてあてはまるわけではなく、PROTECTION_NORMALのものは旧来通りのモデル(インストール時に許可を求める)
・PROTECTION_NORMALて何なの? というと例として、alarm clock、internetが挙げられています
・新しいパーミッションモデルではManifestに<uses-permission-sdk-m>で指定をします。正式リリースでは変わるかも? 変わらないかも?
・パーミッションがあるかないかはContext#checkSelfPermission(String)で調べられる。戻り値はint。PackageManager.PERMISSION_GRANTEDが許可されているintの値。
・Activity#requestPermissions(String[], int)でパーミッションの許可を求める。String[]なのでたぶん一度に複数のパーミッションを要求することができる。これを呼び出すとandroidが許可しますか? ダイアログを出してくれる。第2引数intは許可を求めた結果コールバックの識別に使う
・Activity#onRequestPermissionsResult(int, String[], int[]) : Activity#requestPermissions(String[], int)の結果コールバック。第1引数はrequestPermissionsのintと対応。int[]の要素がPackageManager.PERMISSION_GRANTEDになっているものは許可をされたという意味になる
・Activity#requestPermissionsコール時にandroidが表示するダイアログは「もう一度聞かない」オプションも用意する。これにチェックが入って拒否をされると、Activity#requestPermissionsは即座に拒否される
・テストのためにadbコマンドでパーミッションの許可/拒否ができる
・ベストプラクティス
 ・必要なパーミッションだけを要求する。拒否されたら代替手段を提供する。たとえばカメラの許可がおりなかった時は、暗黙的Intentで別のカメラアプリに撮ってもらう
 ・1度にたくさんのパーミッションを要求しない
 ・なぜパーミッションを必要とするのかを説明する

【サンプルコード】
https://github.com/googlesamples/android-RuntimePermissions

読んでみました。
最初の画面でボタンを押したときのメソッドは下記です。これらはR.layout.fragment_mainのなかでandroid:onClickで指定されています。
com.example.android.system.runtimepermissions.MainActivity#showCamera
com.example.android.system.runtimepermissions.MainActivity#showContacts

この例ではカメラと電話帳のパーミッションを求めています。
許可されていたら、com.example.android.system.runtimepermissions.camera.CameraPreviewFragmentかcom.example.android.system.runtimepermissions.contacts.ContactsFragmentをreplaceしています。これらのFragmentも興味深いのですが割愛します。ContactsFragmentのほうは電話帳へのダミーデータの挿入などがあります。CameraPreviewFragmentはあんまりわかりません。

パーミッションが許可されているかどうかはcom.example.android.system.runtimepermissions.PermissionUtil#hasSelfPermission(android.app.Activity, java.lang.String)というヘルパーメソッドで調べています。中ではContext#checkSelfPermission(String)を使っています。

パーミッションが許可されていなければActivity#requestPermissions(String[], int)で求める。その結果はActivity#onRequestPermissionsResult(int, String[], int[]) で返される。

こんな感じです。
カレンダー、カメラ、電話帳、位置情報等個人情報が特定されるようなパーミッションを必要とするアプリを作るときは注意が必要そうです。

よくわからないのがこれの対象となるパーミッションがどれが該当するのかということです。もしかすると、http://developer.android.com/preview/features/runtime-permissions.htmlのTable 1に書いてあるやつが対象?

従来はインストール時にすべての許可を要求していた




Mからは必要なものは必要なときに




[Raspberry Pi]いろいろインストールしてみる

LXTerminalを使います。

まずは
【ソフトウェア更新】
$ sudo apt-get update
$ sudo apt-get upgrade

【日本語入力】
$ sudo apt-get install ibus-anthy
再起動
右上のIBUSを右クリック->インプットメソッドタブで日本語を追加
こちらが詳しいです。ありがとうございます!

私のキーボードではCtl+Shiftで日本語入力<=>英数字の切り替えでした。

【git】
Gitのインストール
$ sudo apt-get install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
$ cd
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ cd git
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
$ source ~/.bashrc

【rbenv】
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc

【ruby-build】
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

【Ruby】
$ sudo apt-get install libreadline-dev
# 上記を先にインストールしておいたほうがいいとおもいます。これが先にないとあとでrailsをいれたときにもう一回Rubyのインストールをすることになるとおもいます。
$ rbenv instal 2.0.0-p645
$ rbenv global 2.0.0-p645
$ rbenv rehash

【mruby】
* gcc => 入っていました
* bison
 $ sudo apt-get install bison
* Ruby
* mrubyソースコード
  $ cd
  $ git clone https://github.com/mruby/mruby.git
  $ cd /usr/local/bin
  $ sudo ln -s ~/mruby/bin/mruby mruby
  $ sudo ln -s ~/mruby/bin/mrbc mrbc
  $ sudo ln -s ~/mruby/bin/mirb mirb

【rails】
$ gem update --system 2.0.3
  # Ruby on Rails チュートリアル にバージョンはあわせています。
$ cd
$ nano .gemrc
gem: --no-document
  # nanoはテキストエディタです。viでもなにでも好きなエディタで。~/.gemrcに「gem: --no-document」を書いておくとドキュメントのインストールがスキップされるらしいです。
$ gem install rails --version 4.0.5
$ sudo apt-get install libxslt-dev libxml2-dev libsqlite3-dev
$ sudo apt-get install nodejs

8GBのmicroSDカードなのですが、$ df とやるとまだ半分くらいは余裕があるようです。