音声の再生

音声の再生

MP3ファイルや、応答性の求められない音声データの再生は
android.mediaパッケージの
MediaPlayerクラスを使う

MediaPlayer.setDataSource()
で音声データを設定し

MediaPlayer.start()で再生する

ほとんどの場合、再生ボタンを押して再生になるので

implements OnClickListener, OnPreparedListener, OnCompletionListener

を追記する

そして、メンバ変数の宣言

private Button playPause;
private MediaPlayer mediaPlayer;

そして、onCreate()へ処理を追記する

playPause = (Button)findViewById(R.id.playpause);
playPause.setOnClickListener(this);
playPause.setEnabled(false);

//MediaPlayer 初期化
mediaPlayer = new MediaPlayer();

//再生準備完了の通知を受け取るリスナーの設定
mediaPlayer.setOnPreparedListener(this);

//再生完了の通知を受け取るリスナーの設定
mediaPlayer.setOnCompletionListener(this);

//再生させたい音声データのパス設定
String fileName = "android.resource://" + getPackageName() + "/" + R.raw.bgm;

try{

//音声データをMediaPlayerへ設定
mediaPlayer.setDataSource(this, Uri.parse(fileName));

//音声データを非同期で読み込む
mediaPlayer.prepareAsync();
setButtonText(mediaPlayer);

}catch(IllegalArgumentException e){
 e.printStackTrace();

}catch(SecurityException e){
e.printStackTrace();

}catch(IllegalStateException e){
e.printStackTrace();

}catch(IOException e){
 e.printStackTrace();
}

そして、アプリ終了のときの処理

@Override
public void onDestroy(){
super.onDestroy();

//再生中なら停止させる
if(mediaPlayer.isPlaying()){
 mediaPlayer.stop();
}

//MediaPlayerの解放
mediaPlayer.release();
}

メモリ操作みたいに解放が必要になる

そして、ボタンを押したら再生、停止する処理

@Override
public void onClick(View v){

if(v.getId() == R.id.playpause){
//再生中なら停止させる
if(mediaPlayer.isPlaying()){
 mediaPlayer.pause();
 setButtonText(mediaPlayer);
}
//再生中でないなら再生させる
else{
mediaPlayer.start();
setButtonText(mediaPlayer);
}
}
}

音楽データが再生可能になったときの処理

@Override
public void onPrepared(MediaPlayer mp){
playpause.setEnabled(true);
setButtonText(mp);
}

そして、音楽の再生終了したときにボタンの状態を変える処理

@Override
public void onCompletion(MediaPlayer mp){

setButtonText(mp);
}

ボタンの状態変化の処理
ここでは、表示されるラベルを変更する
ちなみに、これはユーザー関数

private void setButtonText(MediaPlayer mp){
//再生中なら停止へ
if(mp.playing()){
playpause.setText(getString(R.string.stop));

}
//停止中なら再生へ
else{
playpause.setText(getString(R.string.play));
}
}

MediaPlayerクラスは
内部で音楽情報を保持しているため
呼び出し側は、それを考慮して
start()
pause()
を呼び出さないとだめ

もし、呼び出してはならないほうを使うと
IllegalExceptionが発生する

今回は、MediaPlayerを初期化して

再生準備完了のpreparedと
再生完了の playbackCompletedの
状態を受け取るためのリスナーを設定し
これらが呼ばれるまで
ボタンのラベルを停止、再生と切り替えるようにしている

効果音の再生

効果音の再生

Androidの効果音の再生のときには
応答性が速く、短い音声データの再生になるので
android.mediaパッケージの
SoundPoolクラスを使う

res/rawsに音声データ配置して
SoundPool.load()
で読み込んで
SoundPool.play()
で再生する

大抵はタッチしたら音を鳴らすので

implements OnClickListener, OnLoadCompleteListener

を追加する

次に、メンバ変数の宣言

private SoundPool mSoundPool;
private int mSoundID;

あとは、onCreate()の中へ動作の追加をする
まずは、ボタンのインスタンスの取得

findViewById(R.id.button).setOnClickListener(this);
findViewById(R.id.button).setEnabled(false);

//SoundPool初期化
mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);

//音声データの読み込み終了を検知するリスナーの設定
mSoundPool.setOnCompleteListener(this);

//音声データの読み込み開始
mSoundID = mSoundPool.load(this, R.raw.test, 1);

そして、画面破棄したときにSoundPoolを解放するので

@Override
public void onDestroy(){

super.onDestroy();
mSoundPool.release();
}

クリック時の処理も実装

@Override
public void onClick(View v){

if(v.getId() == R.id.button){
//音声の再生
mSoundPool.play(mSoundID, 1.0F, 1.0F, 0,0,1.0F);
}
}

そして、読み込み完了したときの処理を
onLoadComplete()へ実装

@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status){

//音声が読み込み完了したら再生ボタンを有効にする
findViewById(R.id.button).setEnabled(true);
}

最初は
setEnabled(false)でボタン無効化しておき
音声が再生できるようになってから
setEnabled(true)でボタンを押せるようにしている

SoundPool()
の初期化パラメーターは

第1引数は、再生されたSoundPoolで同時再生できる数
今回は1

第2引数は、音声の出力先
今回は、res/raws/でのデータを使ったけど
定数も使える
AudioManager.STREAM_ALERM
アラーム音

AudioManager.STREAM_NOTIFICATION
通知音

AudioManager.STREAM_DTMF
トーン信号音

AudioManager.STREAM_RING
着信音

AudioManager.STREAM_SYSTEM
システム音
となる

第3引数は、再生品質 デフォルトでは0になる

SoundPoolの初期化後、再生したい音楽データをメモリ上にロードする必要があるため
load()を使う

load()の引数は
第1引数は、Contextの設定

第2引数は、再生した音声のリソースID

第3引数は、再生品質を指定する
再生品質は、1が推奨となっている

今回なら
load(this, R.raw.test, 1)
となる

load()を実行すると、戻り値に
int型の soundIDが帰ってくる

soundID は、
読み込まれた音声データの番号なので
あとで再生するのに使う

再生については、自動では再生されないため
取得した soundIDを引数にして
play()で再生する

Raspberry Pi でWebカメラ

Raspberry Pi でWebカメラ

Raspberry Pi にはCSIコネクタにさす専用のコネクタもあるけど
USB接続の Webカメラも使える

UVC対応なら、ドライバをインストールしなくても
させば使える

今回、使った web カメラは
iBUFFALO マイク内蔵320万画素WEBカメラ F2.2ガラスレンズ搭載モデル シルバー BSW32KM03SV

raspberry pi は
Raspberry Pi Type B 512MB ケースセット Pi Tin for the Raspberry Pi – Clear

また電源確保のためセルフパワーのUSBハブを利用
iBUFFALO USB2.0ハブ セルフ&バスパワー 4ポート ACアダプタ付 ブラック 【PlayStation4,PS4 動作確認済】 パソコン/液晶TV[REGZA][AQUOS]対応 BSH4A01BK

まずは web カメラを USBにさす

次に

sudo tail -f /var/log/messages 


webカメラが使えるか調べる

今回のログは

Aug 13 10:49:38 raspberrypi kernel: [ 2511.592147] usb 1-1.3.3: Manufacturer: Etron Technology, Inc.
Aug 13 10:49:38 raspberrypi kernel: [ 2511.789941] media: Linux media interface: v0.10
Aug 13 10:49:38 raspberrypi kernel: [ 2511.819490] Linux video capture interface: v2.00
Aug 13 10:49:38 raspberrypi kernel: [ 2511.856057] uvcvideo: Found UVC 1.00 device BUFFALO BSW32KM03 USB PC Camera (2084:0d03)
Aug 13 10:49:38 raspberrypi kernel: [ 2511.863885] uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround.
Aug 13 10:49:38 raspberrypi kernel: [ 2511.870234] input: BUFFALO BSW32KM03 USB PC Camera as /devices/platform/bcm2708_usb/usb1/1-1/1-1.3/1-1.3.3/1-1.3.3:1.0/input/input2
Aug 13 10:49:38 raspberrypi kernel: [ 2511.874302] usbcore: registered new interface driver uvcvideo
Aug 13 10:49:38 raspberrypi kernel: [ 2511.874336] USB Video Class driver (1.1.1)
Aug 13 10:49:38 raspberrypi kernel: [ 2512.005222] usb_audio: Warning! Unlikely big volume range (=4096), cval->res is probably wrong.
Aug 13 10:49:38 raspberrypi kernel: [ 2512.005260] usb_audio: [3] FU [Mic Capture Volume] ch = 1, val = -4097/-1/1<6>[ 2512.012606] usbcore: registered new interface driver snd-usb-audio

今回の確認項目は

Aug 13 10:49:38 raspberrypi kernel: [ 2511.856057] uvcvideo: Found UVC 1.00 device BUFFALO BSW32KM03 USB PC Camera (2084:0d03)

これが
USBカメラの型番

Aug 13 10:49:38 raspberrypi kernel: [ 2511.874302] usbcore: registered new interface driver uvcvideo

これが
ドライバ uvcvideo が読み込まれたことを示す

Aug 13 10:49:38 raspberrypi kernel: [ 2512.005260] usb_audio: [3] FU [Mic Capture Volume] ch = 1, val = -4097/-1/1<6>[ 2512.012606] usbcore: registered new interface driver snd-usb-audio

これが
サウンドドライバ snd-usb-audio 
が読み込まれたことを示す

次に表示の確認や画質コントロールソフトをインストール

sudo apt-get install uvccapture uvcdynctrl guvcview 

これで本体をディスプレイにつなげればデスクトップ環境で使うことができる

次に
Raspberry Pi 単体で動画配信できるようにする

ホームサーバーなどではこっちを使う

これには MJPG-streamer をつかう

これを使えば、パソコンやスマホブラウザで
Raspberry PI にアクセスすることで使うことができる

ただし MJPG-streamer をインストールするのに
apt-get ではできないので
Subversion をつかう

sudo apt-get install subversion libjpeg-dev imagemagick

次に MJPEG-stremer のソースをsuvbersion でダウンロード

svn co https://svn.code.sf.net/p/mjpg-streamer/code/mjpg-streamer mjpg-streamer

そして、コンパイル

cd mjpg-streamer/
make
sudo make install

これでインストール完了

次に MJPEG-streamer の起動

これはスクリプトファイルを作成して実行する

320 x 249 ピクセルの動画を
10fps
これは1秒間に10コマの間隔で配信し
ブラウザはIDとパスワードでアクセスする

今回は ID test パスワード 1234 にする

sudo vim stream.sh

でファイルを作成

#!/bin/bash
PORT="8080"
ID="test"
PW="1234"
SIZE="320x240"
FRAMERATE="10"

export LD_LIBRARY_PATH=/usr/local/lib
mjpg_streamer \
        -i "input_uvc.so -f $FRAMERATE -r $SIZE -d /dev/video0 -y" \
        -o "output_http.so -w /usr/local/www -p $PORT -c $ID:$PW"

そして

chmod 755 stream.sh 

で権限変更

これで
./stream.sh
で実行し
ブラウザで
http://192.168.1.198:8080
でアクセス

ユーザ名 test
パスワード 1234
でアクセスはできたけど
なぜか画像が砂嵐状態

検索して
http://homebrew.jp/show?page=1445
を参考に

sudo ./mjpg_streamer -i "./input_uvc.so -f 15 -r 640x480 -d /dev/video0" -o "./output_http.so -w ./www -p 8080" 

を実行したら動いたので修正

これで再度

./stream.sh 

を実行すれば webカメラの画像が表示される

Raspberry Pi で外付けHDD

Raspberry Pi で外付けHDD

Raspberry Pi をDLNAサーバや
samba をインストールしてNASを構築したときに
SDカードでは容量が少なすぎる

このため Raspberry Pi へ外付けHDDを接続して使う

なお、WiFi アダプタ同様、直接 Raspberry Pi にさすと電力供給の問題で不安定になるので
セルフパワー形式のUSBハブに接続すること

今回使ったのは
MARSHAL(マーシャル) 【160GB】 【USB3.0&USB2.0両対応】外付けポータブルHDD(2.5インチ外付けハードディスクドライブ 160GB MARSHAL WEB限定モデル)

iBUFFALO USB2.0ハブ セルフ&バスパワー 4ポート ACアダプタ付 ブラック 【PlayStation4,PS4 動作確認済】 パソコン/液晶TV[REGZA][AQUOS]対応 BSH4A01BK

本体については
Raspberry Pi Type B 512MB ケースセット Pi Tin for the Raspberry Pi – Clear

を使用

まずはUSBでHDDを接続したときに自動マウントするために

sudo apt-get install usbmount 

で usbmount をインストール

次にマウントするけど
書籍では FAT32 形式フォーマットだけど
購入した外付けHDDはNTFS形式

なので
http://frogcodeworks.com/raspberrypi-hdd-format/
を参考に

sudo apt-get install ntfs-3g


ntfsマウントができるようにする

次に、usbmount の設定ファイルを編集

sudo vim /etc/usbmount/usbmount.conf 


49行めの

FS_MOUNTOPTIONS=""

FS_MOUNTOPTIONS="-fstype=ntfs,uid=pi,gid=pi,iocharset=utf8,codepage=932"

にする

次に、sambaインストール

sudo apt-get install samba samba-common samba-common-bin

次に samba 設定ファイルを編集する

 sudo vim /etc/samba/smb.conf 

そして 33行めの
[global]

の下に

dos charset = CP932
 35 unix charset = UTF8

を追記し
ファイルの末尾に

[share]
path = /media/usb0
valid users =pi
writable = yes
geust = no
guest only = no
create mode = 0777
directory mode = 0777

を追記して保存

そしてsambaのためのユーザとパスワードを設定

sudo smbpasswd -a pi
sudo /etc/init.d//samba restart

で samba を再起動

これでできると思ったけど、どうやらマウントしていない

df -h

で確認しても外付けHDDは認識していない

sudo fdisk -l

では
外付けHDDを認識している

また

dmesg | less | grep sda

では

[    7.833857] sd 0:0:0:0: [sda] 312580096 512-byte logical blocks: (160 GB/149 GiB)

というように認識している

http://mobilenikki.cocolog-nifty.com/wzero3/2013/07/raspberry-pisam.html
を参考に
マウントする方法を実行

sudo mkdir /mnt/share
sudo mount -t ntfs-3g /dev/sda1 /mnt/share

でマウント

これで接続できるはずなので
まずは Ubuntu でアクセス

Nautilus で ネットワークの内容を表示
でRASBERRYPI と表示されているので
これをクリックすれば
共有ファイルへアクセスするために
ユーザ名
パスワードを聞かれるので
入力すればアクセスできる

ただし
これだと毎回コマンドを打つ必要があり面倒
なので
http://raspberrypi.blog.fc2.com/blog-entry-51.html
を参考に

sudo vim /etc/fstab

で最終行に

/dev/sda1 /mnt/share  ntfs-3g defaults 0 0

を追加

また、現在は中身は見れるけど
書き込みや新規作成ができないので
[share]
path = /media/usb0
valid users =pi
writable = yes
geust = no
guest only = no
create mode = 0777
directory mode = 0777
[/shell]
を変更

[RaspNAS]
comment=USBHDD
path=/mnt/share
public = Yes
read only = No
writable = Yes
guest ok = Yes
force user = pi

と変更して保存

これでようやく書き込みやファイル作成が可能になりました

GMOクラウドのネットワーク再構築

GMOクラウドのネットワーク再構築

wordpress の投稿を行おうとしたところ
データベース接続確立エラー
となり接続できなくなったため

以前対処したように、
クラウドコンソールからログインし状態を確認

ダッシュボードから仮想マシンの状態を確認したところ
Pending のままになっていた

このため
仮想サーバー > 使用しているマシンのラベル名をクリック

そして、アクションの項目にある
ネットワークの再構築をクリックしOK
をおすとネットワークの再構築が始まる

しばらく待つと、状態が Pending のままから
complete になるので
これで再度接続すると問題は解決さえた

メンテの後などにたまにあるので
もし wordpress に接続できなくなったり
SSHでの接続もできなくなった場合
一度クラウドコンソールで状態が Pending のままになっていないか調べるようにすると解決するヒントが得られる

画像のピンチイン、ピンチアウト

画像のピンチイン、ピンチアウト

これは、Viewの拡大、縮小に使う

画像をピンチイン、ピンチアウトするには
Bitmapクラスと
ScaleGestureDetectorクラスを
メンバ変数に持つ独自Viewクラスを作成する

独自Viewクラスでは、
コンストラクタの実装と
onDraw()
onTouchEvent()
のOverrideをする

まず、

class MyView extends View

でViewを継承

そして、メンバ変数の宣言 

private Bitmap mBitmap;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.0f;

そして、コンストラクタの実装

public MyView(Context context){

super(context);
try{
InputStream is = getResources().getAssets().open("test.jpg");
mBitmap = BitmapFactory.decodeStream(is);
}catch(Exception e){
}
mScaleDetector = new ScaleGestureDetector(context, 
new ScaleGestureDetector.SimpleOnScaleGestureListener(){

@Override
public boolean onScale(ScaleGestureDetector detector){

mScaleFactor *= detector.getScaleFactor();
invalidate();
return true;
}
}
);
}

次に、onDraw()の実装

protected void onDraw(Canvas canvas){

canvas.save();

canvas.scale(mScaleFactor, mScaleFactor);

canvas.drawBitmap(mBitmap, 0,0, null);

canvas.restore();
}

そして、onTouchEvent()のOverride

public boolean onTouchEvent(MotionEvent e){
mScaleDetector.onTouchEvent(e);
return true;
}

コンストラクタでは、画像読み込みと
ScaleGestureDetectorクラスの生成をする

ScaleGestureDetectorクラスの
コンストラクタに
SimpleOnScaleGestureListenerクラスをパラメーター指定することで
スケール変更に関するイベントを処理できるようになる

SimpleOnScaleListenerクラスの
onScale()で
スケール計算と
再描画を促すために
Viewクラスのinvalidate()を呼び出す

そして、onDraw()で
スケール設定と
画像の描画を実装

onTouchEvent()では、
ScaleGestureDetectorクラスの
onTouchEvent()を呼び出す

画像のピンチイン、ピンチアウト

画像のピンチイン、ピンチアウト

これは、Viewの拡大、縮小に使う

画像をピンチイン、ピンチアウトするには
Bitmapクラスと
ScaleGestureDetectorクラスを
メンバ変数に持つ独自Viewクラスを作成する

独自Viewクラスでは、
コンストラクタの実装と
onDraw()
onTouchEvent()
のOverrideをする

まず、

class MyView extends View

でViewを継承

そして、メンバ変数の宣言 

private Bitmap mBitmap;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.0f;

そして、コンストラクタの実装

public MyView(Context context){

super(context);
try{
InputStream is = getResources().getAssets().open("test.jpg");
mBitmap = BitmapFactory.decodeStream(is);
}catch(Exception e){
}
mScaleDetector = new ScaleGestureDetector(context, 
new ScaleGestureDetector.SimpleOnScaleGestureListener(){

@Override
public boolean onScale(ScaleGestureDetector detector){

mScaleFactor *= detector.getScaleFactor();
invalidate();
return true;
}
}
);
}

次に、onDraw()の実装

protected void onDraw(Canvas canvas){

canvas.save();

canvas.scale(mScaleFactor, mScaleFactor);

canvas.drawBitmap(mBitmap, 0,0, null);

canvas.restore();
}

そして、onTouchEvent()のOverride

public boolean onTouchEvent(MotionEvent e){
mScaleDetector.onTouchEvent(e);
return true;
}

コンストラクタでは、画像読み込みと
ScaleGestureDetectorクラスの生成をする

ScaleGestureDetectorクラスの
コンストラクタに
SimpleOnScaleGestureListenerクラスをパラメーター指定することで
スケール変更に関するイベントを処理できるようになる

SimpleOnScaleListenerクラスの
onScale()で
スケール計算と
再描画を促すために
Viewクラスのinvalidate()を呼び出す

そして、onDraw()で
スケール設定と
画像の描画を実装

onTouchEvent()では、
ScaleGestureDetectorクラスの
onTouchEvent()を呼び出す


から送られてきた高速メモ帳

raspberry pi で無線LAN

raspberry pi で無線LAN

Raspberry Pi には有線LANのポートしかないけど
USBアダプタタイプのWiFiアダプタを使えば
Raspberry Pi でも無線LANが使える

注意点としては WiFi アダプタを使うには
消費電力が大きいため
Raspberry Pi へ直接さすのではなく
セルフパワー形式のUSBハブ経由で接続する

今回使用した部品は
【Amazon.co.jp限定】PLANEX 無線LAN子機 (USBアダプター型) 11n/g/b 150Mbps GW-USNANO2A (FFP)

iBUFFALO USB2.0ハブ セルフ&バスパワー 4ポート ACアダプタ付 ブラック 【PlayStation4,PS4 動作確認済】 パソコン/液晶TV[REGZA][AQUOS]対応 BSH4A01BK

使用した本体は
Raspberry Pi Type B 512MB ケースセット Pi Tin for the Raspberry Pi – Clear

まずは WiFiアダプタが Raspberry Pi で使えるか確認する

sudo tail -f /var/log/messages 

で直近のログ10項目を出力できる

ログは

Aug 10 20:28:52 raspberrypi kernel: [    4.536558] usb 1-1.3.1: Product: GW-USNANO2
Aug 10 20:28:52 raspberrypi kernel: [    4.536566] usb 1-1.3.1: Manufacturer: Planex Communications Inc.
Aug 10 20:28:52 raspberrypi kernel: [    4.536574] usb 1-1.3.1: SerialNumber: 00e04c000001
Aug 10 20:28:52 raspberrypi kernel: [    6.950191] bcm2708-i2s bcm2708-i2s.0: Failed to create debugfs directory
Aug 10 20:28:52 raspberrypi kernel: [    8.706115] usbcore: registered new interface driver rtl8192cu
Aug 10 20:28:52 raspberrypi kernel: [   11.921089] EXT4-fs (mmcblk0p6): re-mounted. Opts: (null)
Aug 10 20:28:52 raspberrypi kernel: [   12.605644] EXT4-fs (mmcblk0p6): re-mounted. Opts: (null)
Aug 10 20:28:52 raspberrypi kernel: [   22.039343] smsc95xx 1-1.1:1.0 eth0: hardware isn't capable of remote wakeup
Aug 10 20:28:52 raspberrypi kernel: [   23.661375] smsc95xx 1-1.1:1.0 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Aug 10 20:28:54 raspberrypi kernel: [   28.335735] Adding 102396k swap on /var/swap.  Priority:-1 extents:1 across:102396k SSFS

この中で確認するべきは
raspberrypi kernel: [ 4.536558] usb 1-1.3.1: Product: GW-USNANO2

raspberrypi kernel: [ 8.706115] usbcore: registered new interface driver rtl8192cu
の部分

Product: GW-USNANO2
が製品名

driver rtl8192cu
がドライバになる

なおログ出力状態からでるには
Ctrl + c
ででれる

次に、無線LANのデバイスを認識しているか調べるために

iwconfig

を実行

これで

wlan0     unassociated  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency=2.412 GHz  Access Point: Not-Associated   
          Sensitivity:0/0  
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

lo        no wireless extensions.

eth0      no wireless extensions.

というように
wlan0 がでていればOK

もし有線LANだけしか認識していないなら
eth0 しかでない

次にコマンドラインから無線LANへの接続

デスクトップ環境をたちあげることで設定もできるけど
コマンドラインで設定できる方法をしっていれば
SSH経由で設定もできる

まずはSSIDを調べる

sudo iwlist wlan0 scan

これで
実行結果の中で ESSID のところにアクセスポイントがでるのでこれを覚えておく

次に、SSIDとパスワードの設定

sudo sh -c "wpa_passphrase SSID名 無線LANのパスワード >> /etc/wpa_supplicant/wpa_supplicant.conf"

とする

もし
SSIDが test
パスワードが password なら

sudo sh -c "wpa_passphrase test password >> /etc/wpa_supplicant/wpa_supplicant.conf"

となる

これで設定できたかを調べるには

sudo cat /etc/wpa_supplicant/wpa_supplicant.conf 

とすればOK

ここまでできたら、無線LAN機能を再起動する

sudo ifdown wlan0
sudo ifup wlan0

これで無線LAN機能が再起動するので

iwconfig

で状態を確認する

もし無線LANの IP アドレスなどを知りたいのなら

ifconfig

とすれば無線LANでのIPも見ることができる

大きい画像の表示

大きい画像の表示

大きな画像は、リサンプルして読み込むことで
読み込み速度の向上
大きな画像を読み込むときに問題になる
OutOfMemoryを未然に防ぐことができる

まずは、画像情報の取得

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds();

input = getContentResolver().openInputStream(imageUri);
BitmapFactory.decodeStream(input,null,options);

次に、リサンプルの計算

int inSampleSize = calculateInSampleSize(options,MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);

そして、ユーザー関数 calculateInImageSize()の定義

これは、必要な画像サイズを渡すと
そのサイズにあったリサンプル値を返す

private int calculateInSampleSize(BitmapFactory.Options, int reqWidth, int reqHeight){

final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if(height > reqHeight || width > reqWidth){

if(width > height){

inSampleSize = Math.round((float)height / (float)reqHeight);

}else{

inSampleSize = Math.round((float)width / (float)reqWidth);
}
}
return inSampleSize;
}

これで、値の算出ができるので
次に、リサンプルして画像を読み込む

options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;

input = getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(input,null,options);

大きな画像を読み込むと
画像が端末のメモリに入りきらず
OutOfMemoryが発生してアプリが終了することがある

これをふせぐため
画像の情報を事前に読み込み 
幅、高さからリサンプル値を求め
画像に適切な大きさにすることで
OutOfMemoryを防止できる

今回、画像情報を読み込むため
BitmapFactory.Optionsの
inJustDecodeBoundsフラグを trueにして
画像のヘッダ情報だけ読み込む

この場合、画像本体は読み込んでないので高速に処理できる

その後に、画像情報からリサンプル値を求め
再度
inJustDecodeBoundsにfalseを設定することで
画像全体を読み込む

つまり、
inJustDecodeBoundsが
trueならヘッダ情報だけ
falseなら全部読み込む

このときにinSampleSizeにリサンプル値を設定することで
適切な解像度で画像を読み込める

画像の反射表示

画像の反射表示

画像の反射は、オリジナル画像と反転した画像を縦に並ぶように配置し
反転画像の部分に
グラデーションを重ねるように描画することで実現する

まずは、Bitmap画像の読み込み
今回は loadBitmap()を定義し
引数として画像のURIを渡すと
ContentProvider経由で取得した画像のBitmapインスタンスを返す

Bitmap bitmapOriginal = loadBitmap(imageUri);

そして、反射された画像を作成するMatrixを生成

Matrix matrix = new Matrix();
matrix.preScale(1,-1);
int height = bitmapOriginal.getHeight();
int width = bitmapOriginal.getWidth();

そして、反転された画像を書き込むBitmapの作成

Bitmap reflectionImage = Bitmap.createBitmap(bitmapOriginal,0, height/2, width,height/2,matrix, false);

そして、オリジナル画像に反転した画像を合成したイメージを書き込むBitmapを作成

Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height/2), Config.ARGB_8888);

そして、オリジナル画像と反転画像をもとに反射画像を生成

//最終的なイメージを書き込むBitmap作成
Canvas canvas = new Canvas(bitmapWithReflection);

//オリジナル画像描画
canvas.drawBitmap(bitmapOriginal, 0,0,null);
Paint defaultPaint = new Paint();

//継ぎ目を目立たなくするため、デフォルトの色を描画
canvas.drawRect(0, height, width, height + REFLECTIONGAP, defaultPaint);

//反転イメージの描画
canvas.drawBitmap(reflectionImage, 0, height+ REFLECTIONGAP,null);

//反転されたイメージ画像を下へいくごとに白くなるグラデーションを設定
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(
0,
bitmapOriginal.getHeight(), 
0,
bitmapWidthReflection.getHeight()+ REFLECTIONGAP,
0x70ffffff,
0x00ffffff,
TileMode.CLAMP
);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));

//グラデーション描画
canvas.drawRect(0,height,width,bitmapWithReflection.getHeight(),REFLECTIONGAP,paint);

反転画像は、
Bitmap.createBitmap()の第6引数の
Matrixで、回転行列
つまり角度みたいなのを設定することで
反転画像をつくれる

反転画像は、画面の下側に反射したかんじで表現する

色を変えないのなら
湖とかに写るような演出もできる

さらに、遠くになるほどぼやけるようにすれば
さらにそれっぽい
例えば、反転画像を下へいくほど
白のグラデーションを上乗せするなど

グラデーションのやり方は
PaintクラスのsetShader()で行い

setXfermode()で、グラデーションのピクセル単位の計算方法を指定して描画する