2015年9月19日土曜日

[Ruby]国勢調査パスワード

国勢調査インターネット回答やりましたか?

回答の最後に8文字以上32文字以内のパスワードを決めないといけないのですが、その際のパスワードをランダムに生成するRubyワンライナーです。


ruby -e "puts [*(0..9), *('a'..'z'), *('A'..'Z'), '#', '$', '-', '=', '?', '@', '[', ']', '_'].sample(32).join"


2015年8月27日木曜日

[Ruby]Fizz Buzz

Fizz Buzzを小難しく書いてみました。
ルールが変わったら、@rule_pairsの初期値を変えればよいはず。
[[:fizz, 3], [:buzz, 5] , [:torifuku, 10] ]とか。

module FizBuzz
  class << self
    private
    def rule_pairs
      @rule_pairs ||= [[:fizz, 3], [:buzz, 5]].map(&:freeze).freeze
    end
  end

  method_names = rule_pairs.map(&:first).map(&:freeze).freeze
  define_method(:say) do
    value = method_names.map{|name| lambda{__send__ name}}.inject('') do |result, proc|
      result + proc.()
    end
    value.empty? ? self : value
  end

  private
  rule_pairs.each do |sym, n|
    define_method("#{sym}?") do
      self % n == 0
    end

    define_method(sym) do
      __send__("#{sym}?") ? sym.to_s.capitalize : ''
    end
  end
end

class Integer
  include FizBuzz
end

p (1..100).map(&:say)
p FizBuzz.private_methods.grep /rule_pairs/ # => [:rule_pairs]
p FizBuzz.public_instance_methods.grep /say/ # => [:say]
p FizBuzz.private_instance_methods.grep /[fi|bu]zz/ # => [:fizz?, :fizz, :buzz?, :buzz]

以下のようなメソッドを定義しています。
p FizBuzz.private_methods.grep /rule_pairs/ # => [:rule_pairs]
p FizBuzz.public_instance_methods.grep /say/ # => [:say]
p FizBuzz.private_instance_methods.grep /[fi|bu]zz/ # => [:fizz?, :fizz, :buzz?, :buzz]

2015年8月22日土曜日

[Raspberry Pi][android]adb(Android Debug Bridge)を作る

SDK Tools Onlyからダウンロードしたadbはそのままでは使えませんでした。
ARM用のコンパイルしたadbが必要なようです。

いろいろ調べると結局Adb for Raspberry piにいきつくようです。
Thanks a lot!

ちょっと古いソース(2014年/9月ころ)を使うことになりますが、adbがビルドできましたのでメモを残しておきます。
http://forum.xda-developers.com/showthread.php?t=1924492&page=7の#70そのままです。

Rasbian(LXTerminal)上で作業を行います。

$ sudo apt-get update
$ sudo apt-get install git build-essential libncurses5-dev libssl-dev
$ mkdir aosp
$ cd aosp
$ git clone https://android.googlesource.com/platform/system/core.git system/core
$ git clone https://android.googlesource.com/platform/external/zlib.git external/zlib

あとで作成するMakefileが使えるようにあるコミットIDをチェックアウトします。
$ cd system/core
$ git checkout -b topic 32e2f1be039482762303378113c817ba99466953
$ cd ../../
$ cd external/zlib
$ git checkout -b topic 8d977782c1cfe9d75cc9a464439c2ff1e27e1665

system/core/adb/Makefile を作ります。

SRCS+= adb.c
SRCS+= adb_client.c
SRCS+= commandline.c
SRCS+= console.c
SRCS+= file_sync_client.c
SRCS+= fdevent.c
SRCS+= get_my_path_linux.c
SRCS+= services.c
SRCS+= sockets.c
SRCS+= transport.c
SRCS+= transport_local.c
SRCS+= transport_usb.c
SRCS+= usb_linux.c
SRCS+= usb_vendors.c
SRCS+= adb_auth_host.c

VPATH+= ../libcutils
SRCS+= socket_inaddr_any_server.c
SRCS+= socket_local_client.c
SRCS+= socket_local_server.c
SRCS+= socket_loopback_client.c
SRCS+= socket_loopback_server.c
SRCS+= socket_network_client.c
SRCS+= load_file.c

VPATH+= ../libzipfile
SRCS+= centraldir.c
SRCS+= zipfile.c

VPATH+= ../../../external/zlib/src
SRCS+= adler32.c
SRCS+= compress.c
SRCS+= crc32.c
SRCS+= deflate.c
SRCS+= infback.c
SRCS+= inffast.c
SRCS+= inflate.c
SRCS+= inftrees.c
SRCS+= trees.c
SRCS+= uncompr.c
SRCS+= zutil.c

CPPFLAGS+= -DADB_HOST=1
CPPFLAGS+= -DHAVE_FORKEXEC=1
CPPFLAGS+= -DHAVE_SYMLINKS
CPPFLAGS+= -DHAVE_TERMIO_H
CPPFLAGS+= -DHAVE_OFF64_T
CPPFLAGS+= -D_GNU_SOURCE
CPPFLAGS+= -D_XOPEN_SOURCE
CPPFLAGS+= -DWORKAROUND_BUG6558362
CPPFLAGS+= -I.
CPPFLAGS+= -I../include
CPPFLAGS+= -I../../../external/zlib

CFLAGS+= -O2 -g -Wall -Wno-unused-parameter
#LDFLAGS= -static
LIBS= -lrt -lpthread -lcrypto -lssl

TOOLCHAIN=
CC= $(TOOLCHAIN)gcc
LD= $(TOOLCHAIN)gcc

OBJS= $(SRCS:.c=.o)

all: adb

adb: $(OBJS)
  $(LD) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)

clean:
  rm -rf $(OBJS)

最後の4行くらいの
「$(LD) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)」と「rm -rf $(OBJS)」の前はタブです。
Makefileを作ったら、

$ cd system/core/adb
$ make adb
-> adbができています!


$ sudo ./adb kill-server
$ sudo ./adb start-server
$ ./adb devices


$ uname -a
Linux raspberrypi 3.18.11-v7+ #781 SMP PREEMPT Tue Apr 21 18:07:59 BST 2015 armv7l GNU/Linux
という環境でした。



2015年7月30日木曜日

[android]ストップウォッチアプリをつくりました

まつもと直伝 プログラミングのオキテ 第20回 MVCとRuby on Rails でMVCの説明の題材となっているRubyでかかれたストップウォッチのサンプルをandroidアプリとして書いてみました。

TORIFUKUKaiou/StopWatch

Enjoy!


2015年7月29日水曜日

[android]Add Tabs to the Action Barはdeprecated → com.android.support:design

久しぶりにアプリを更新しようとおもって、ライブラリの更新とかをやっていると、Add Tabs to the Action Barの内容で作った箇所がまるまるdeprecatedになっていました。
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS)
android.support.v7.app.ActionBar.Tab
android.support.v7.app.ActionBar.TabListener
等がdeprecatedです。

どうしようか途方にくれておりましたところ、com.android.support:designの導入で解決しましたのでご紹介しておきます。

おおまかには次の手順で移行できます。
1. com.android.support:designを使えるようにする。app/src/build.gradleに
compile 'com.android.support:design:22.2.1' みたいなのを追加する感じです
2. android.support.design.widget.TabLayoutとandroid.support.v4.view.ViewPagerを上下に並べたレイアウトを用意する
3. TabLayoutとViewPagerを結びつける。tabLayout.setupWithViewPager(mViewPager);な感じです。

私の場合はViewPagerはそのまま使えました。

とても参考にさせていただきました。ありがとうございます。
Android Design Support Libraryを使う
Design Support Library v22.2.0について Part 3

Enjoy!


2015年7月27日月曜日

[Ruby]最長重複文字列問題

こんな感じ?

class Array
  def tail
    ary = dup
    ary.empty? ? [] : ary.drop(1)
  end

  def tails
    ary = dup
    ary.empty? ? [[]] : ([ary] + ary.tail.tails)
  end
end

class String
  def max_dup_string
    ary = dup.split('')
    ary.tails.sort.tail.zip(ary.tails.sort).map do |fst, snd|
      fst.zip(snd).take_while{|l, r| l == r}.map{|l, r| l}.join.strip
    end.sort{|a, b| b.length <=> a.length}[0]
  end
end

p "Ask not what your country can do for you, but what you can do for your country".max_dup_string
# => "can do for you"
p "Hello, World. Hello, Ruby!".max_dup_string
# => "Hello,"
p "mississippi".max_dup_string
# => "issi"

$ ruby -v
ruby 2.0.0p645 (2015-04-13 revision 50299) [x86_64-darwin14.4.0]

Enjoy!


2015年7月14日火曜日

クイックソート

Haskellをかじりはじめました。
この本で勉強しています。

2006年のものなのでちょっと古いのかもしれませんが、初心者にはとてもわかりやすいです。
ありがとうございます。
本でつかっているghcのバージョンは6.2.2でいまの最新は7.8.4のようです。
本文中のimportのところは下記のように読み替えると大丈夫でした。
import System -> import System.Environment
import List -> import Data.List

qsort [] = []
qsort (p:xs) = qsort lt ++ [p] ++ qsort gteq
                where
                  lt   = [x | x <- xs, x < p]
                  gteq = [x | x <- xs, x >= p]
慣れないうちはなんのことやら? だったのですが、上くらいのことがわかるようになるとクイックソートのことがすっきりとわかるようになりました。


Rubyで書いてみました。
def qsort(ary)
 ary.empty? ?
     [] :
     qsort(ary.drop(1).select{|n| n < ary[0]}) + [ary[0]] + qsort(ary.drop(1).select{|n| ary[0] <= n})
end
p qsort([10, 9, 8, 7, 6, 5, 1000, 0]) # ①
p qsort(%w|hello goodby こんにちは 6 5 1000 0 Ruby Python Haskell C C++ Java|) # ②

①はNumericの配列のソートです。
②はStringの配列のソートです。
まったく同じメソッドがそのまま使えます。
これはFixnumクラス、Stringクラスがmodule Comparableをincludeしていて、
<=>演算子(メソッド)を定義しているので各要素の比較が可能であるためです。
ポリモーフィズムというやつです。
Array#drop(n)はnが1だったら[4,5,6] -> [5,6]を返すメソッドです。nは落とす個数を指定するらしいです。
drop(1)はHaskellのtailと同じ意味あいになるかとおもわわれます。

Arrayにモンキーパッチしてみました。
上の例はpivotを必ず先頭から選んでいますが、ランダムに選ぶようにしてみました。
class Array
  def qsort(ary=self)
    ary.empty? ?
      [] :
      (ary = ary.dup
       pivot = ary.delete_at(rand(ary.length))
       qsort(ary.select{|n| n < pivot}) + [pivot] + qsort(ary.select{|n| pivot <= n}))
  end
end

ary = [10, 9, 8, 7, 6, 5, 1000, 0]
p ary.qsort
p ary # 上の例では新しいArrayインスタンスを返しているので、元の並び順は変更されません。


結局こうすればよいのかもしれません。
module TorifukuModule
  extend self

  def qsort(ary=self)
    ary.empty? ?
      [] :
      (ary = ary.dup
       pivot = ary.delete_at(rand(ary.length))
       qsort(ary.select{|n| n < pivot}) + [pivot] + qsort(ary.select{|n| pivot <= n}))
  end
end

class Array
  include TorifukuModule
end

ary = [10, 9, 8, 7, 6, 5, 1000, 0]
p ary.qsort
p TorifukuModule.qsort(ary)

$ ruby -v
ruby 2.0.0p645 (2015-04-13 revision 50299) [x86_64-darwin14.4.0]

enjoy!

2015/07/27追記
ary=selfがなんか変だなあとおもっていました。
こうすればいいのかもしれません。

module TorifukuModule
  def qsort
    empty? ?
      [] :
      (ary = dup
       pivot = ary.delete_at(rand(ary.length))
       ary.select{|n| n < pivot}.qsort + [pivot] + ary.select{|n| pivot <= n}.qsort)
  end
end

class Array
  include TorifukuModule
end

ary = [10, 9, 8, 7, 6, 5, 1000, 0]
p ary.qsort





2015年7月12日日曜日

フィボナッチ数列

フィボナッチ数列を書いてみました。
Hashのnewの時に渡したblockは、Hashにキーがまだ含まれていないときの初期値を定義します。
これを利用してみました。
case - when 式も練習してみました。

h = Hash.new do |hash, key|
  hash[key] = case key
              when 0 then 0
              when 1 then hash[0] = 0 unless hash.has_key?(0); 1
              else hash[key-1] + hash[key-2]
              end
end

puts h[100]
p h.values

$ ruby -v
ruby 2.0.0p645 (2015-04-13 revision 50299) [x86_64-darwin14.4.0]

class Hashによると、「ハッシュに含まれる要素の順序が保持されるようになりました。 ハッシュにキーが追加された順序で列挙します。」とのことなので、h.valuesで順番通りのArrayインスタンスが得られています。


2015年7月11日土曜日

[Raspberry Pi]7セグLEDを表示してみる

7セグLEDの説明は「7セグ LED と集合抵抗を使ってみよう」が詳しいです。
参考にさせていただきました。ありがとうございます。

私はカソードコモンを使いました。また端子は上下にあるものを使いました。
抵抗は1kΩのものを使いました。



* 3番(下側中央)をGNDに接続しています。GNDに接続するのは8番(上側中央)でもいいみたいです。
* 7個のLED(AからG)にそれぞれHigh(点灯)、Low(消灯)を指示することで数字の表示ができます。
* 私の場合は以下のような回路になっています。
7セグLEDのA : GPIO 5
7セグLEDのB : GPIO 13
7セグLEDのC : GPIO 6
7セグLEDのD : GPIO 20
7セグLEDのE : GPIO 21
7セグLEDのF : GPIO 16
7セグLEDのG : GPIO 19
  * GPIOの番号は「GPIO: MODELS A+, B+ AND RASPBERRY PI 2」の上側の図の番号体系と同じです。
  * プログラム中のled_gpio_dicと対応しておりまして、Value(右側の数字)は何番のGPIOにつないだかによって変更する必要があります。
* またGPIO 24がHigh(スイッチを押したとき)になったら停止するようにしています。
* プログラムはPythonで書きました。
 * $ sudo python filename.py
   で実行できます。

import RPi.GPIO as GPIO
from time import sleep

# 7seg led position : GPIO
led_gpio_dic = {
    "A": 5,
    "B": 13,
    "C": 6,
    "D": 20,
    "E": 21,
    "F": 26,
    "G": 19 }

# number : led position
number_led_dic = {
    0: set([chr(c) for c in range(ord('A'), ord('F')+1)]), # A, B, C, D, E, F
    1: set(["B", "C"]), # B,C
    2: set(["A", "B", "G", "E", "D"]), # A, B, G, E, D
    3: set(["A", "B", "C", "D", "G"]), # A, B, C, D, G
    4: set(["F", "G", "B", "C"]), # F, G, B, C
    5: set(["A", "F", "G", "C", "D"]), # A, F, G, C, D
    6: set(["F", "E", "D", "C", "G"]), # F, E, D, C, G
    7: set(["A", "B", "C"]), # A, B, C
    8: set([chr(c) for c in range(ord('A'), ord('G')+1)]), # A, B, C, D, E, F, G
    9: set(["A", "B", "C", "F", "G"]), # A, B, C, F, G
    "-": set(["G"]) }

def my_callback(channel):
    global done
    if channel == 24:
        done = True

def show(number):
    high_pos_set = number_led_dic[number]
    low_pos_set = number_led_dic[8] - high_pos_set
    for pos in high_pos_set:
        GPIO.output(led_gpio_dic[pos], GPIO.HIGH)
    for pos in low_pos_set:
        GPIO.output(led_gpio_dic[pos], GPIO.LOW)

# init
GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback, bouncetime=200)
for pos in number_led_dic[8]:
    GPIO.setup(led_gpio_dic[pos], GPIO.OUT, initial = GPIO.LOW)


done = False
num = 0
try:
    while not done:
        show(num % 10)
        num += 1
        sleep(0.3)
except KeyboardInterrupt:
    pass

GPIO.cleanup()


【環境】
Raspberry Pi 2 Model B
$ uname -a
Linux raspberrypi 4.0.7-v7+ #801 SMP PREEMPT Tue Jun 30 18:38:23 BST 2015 armv7l GNU/Linux



Enjoy!



2015年7月4日土曜日

[Raspberry Pi][Python]教材

Raspberry PiのPiはPythonに由来しているそうで、Pythonを勉強しようかなあとおもっていたところいい教材をみつけました。

MagPiです。

MagPiはRaspberry Piの公式雑誌です。PDFは無料で読めます。
2012/Mayの創刊号から読めます。

MagPiのなかに「the python(TM) pit」というコーナーがありまして、じっくりPythonを説明してくれるそうです。
最初の3つくらいを斜め読みしてみると、pygameの話題が多いかもしれません。

2012/Mayの創刊号をやってみました。
pygameを使ったBAT AND BALLというゲームを打ち込んでみました。
落ちてくるボールをバットで打ち返すゲームです。

ちなみにバックナンバーはここから読めます。




まつもとゆきひろ氏が「生涯プログラマー」でやっていきたい若手に贈る3つの言葉【特集:エンジニア育成の本質】で触れられているような100行程度のゲームプログラムを打ち込む体験が平成の今できます。

Enjoy!


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 とやるとまだ半分くらいは余裕があるようです。

2015年5月31日日曜日

[Raspberry Pi]Raspberry Pi を買いました


Raspberry Pi を買いました。

OSはRASPBIANをインストールしました。

【必要なもの】
・Raspberry Pi本体(Raspberry Pi 2 Model B)
・USB-ACアダプター(セットで買ったのでよくわからないのですが何でもよいわけではないようです)
・microSDカード(8GB以上でSDHCクラス10またはUHSがいいらしいです)
・HDMIケーブル(Raspberry側はタイプAです)
・ディスプレイ
・LANケーブル
・マウス(USB)
・キーボード(USB)
ディスプレイにHDMIがなかったので、HDMI → DVI変換コネクタ → ディスプレイとつないています。

セットアップはmicroSDカードにNOOBS(1.4.1 / 2015-05-11)というのをコピーしてから、それ経由でRASPBIANをインストールしました。
RASPBIANというのは最低限必要なソフトだけが入っているLinuxみたいな感じでしょうか。あとから自分でいろいろ追加していきます。

方法はここに詳しく書いてあります。

初めてRASPBIANを起動すると「raspi-config」というのが表示されます。
書籍を参考に下記の設定をしました。
あとから「raspi-config」を起動するにはLXTerminalで$ sudo raspi-config です。
I1 Change Locale: ja_JP.UTF-8
I2 Change Timezone: Asia -> Tokyo
I3 Change Keyboard: Generic 101-key PC -> Other -> Japanese -> Japanese -> The default ... -> No compose key -> Yes

最後にFinish
Passwordもここで変えておいたほうがいいかもしれません。
デフォルトはraspberryです。

raspberry pi login: pi
Password: raspberry

$ startx



GUIが起動します!

この時点でもいろいろ入っています。

LXTerminalでバージョンを確かめてみました。
$ git --version
git version 1.7.10.4

$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [arm-linux-eabihf]

pythonとか他のソフトウェアも入っていました。

[android]AdapterView.OnItemClickListener#onItemClickのpositionについて


listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView parent, View view, int position, long id) {
    // positionでitemを取得する★
  }
});

「// positionでitemを取得する★」のところで、ArrayAdapterの生成のときに渡したListインスタンスからList#getでItemを取得するようなコードを書いていました。よく。。。

ある日これではだめなことがわかりました。
listView.addHeaderView(header, null, false);
上にくっつきすぎている気がして、ヘッダーを追加したんです。
すると、+1された位置のものが返されるようになって、Listインスタンスから取得しているものだから最後尾のアイテムを触るとArrayIndexOutOfBoundsExceptionが発生するようになりました……

http://stackoverflow.com/questions/11106397/listview-addheaderview-causes-position-to-increase-by-one
に答えがありました。
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
        Klass item = (Klass)(parent.getItemAtPosition(position));
        // Klassは任意のクラス
}
});

こちらとか2011年10月4日から上のようになっています。
先人のサンプルをよく研究することが大事だとおもいました。