My Photo

« December 2011 | Main | February 2012 »

January 31, 2012

Androidアプリ開発メモ060:画面が回転するとonDestroy()が呼ばれる

関連する記事:
Androidアプリ開発メモ027:画面の向き
Androidアプリ開発メモ057:AVDの画面の向きを変更する

画面を回転させるとonDestroy()が呼ばれてActivityが破棄され、onCreate()が呼ばれて新たなActivityが作られる。
これを避ける方法として、参考ページではAndroidManifest.xmlでActivity要素にandroid:screenOrientation属性を指定して画面の向きを固定した上で、センサから回転を取得して自力が表示を回転する処理を実装する方法を載せている。

自分が今作っているタイマーアプリでは、横向き画面が必要とは思えないのでandroid:screenOrientation属性を指定するだけにしておいた。

参考ページ:Androidアプリの画面回転時にonDestroyさせない方法 | Tech Booster

Androidアプリ開発メモ059:スリープから復帰させる

関連する記事:Androidアプリ開発メモ058:ロック画面を出さないようにする

「スリープから復帰させる」と言っても、そもそもどういう状態をスリープというのかがわからない。
電源は入っているけど画面の真っ暗の状態のことではないとどこぞに書いてあったが、自分としては
「しばら端末を操作せずに置いて画面が真っ暗になった状態」
だと思っている^^;

スリープから復帰させるにはまず PowerManager を getSystemService() で取得し、その PowerManager#newWakeLock() で WakeLock を取得して acquire() でロックを取得する。
ロックを取得したら、適切なタイミングでロックを release() しなければならない。そうしないとリソースの解放漏れ?ずっとスリープにならなくなる?

android.os.PowerManagerクラス
public PowerManager.WakeLock newWakeLock(int flags, String tag)
フラグパラメータのレベルにあるウェイクロックを得る。ウェイクロックを取得するためにそのオブジェクト上で acquire() を呼び、終わったら release() を呼ぶ。
もしスクリーンをonにキープするためにこれを使うなら、代わりに FLAG_KEEP_SCREEN_ON を使うことを考えるべきである。このwindowフラグはプラットフォームによって正確に管理されるだろう、ユーザがアプリケーション間を動くときに。そして特別なパーミッションを必要としない。
引数
  flags  フラグ値の組み合わせ
  tag    デバッグのためのクラス名(または他のタグ)

android.os.PowerManager.WakeLockクラス
public void acquire()
デバイスをウェイクアップロックを作成したときに要求したレベルでオンにする。

android.os.PowerManager.WakeLockクラス
public void release()
CPUまたは画面がonであるという主張をリリースする。
リリースされ後すぐにoffになるだろう。すなわち他の保持されているロックがあればoffにならないだろう。

newWakeLock() で指定するフラグは、スリープ状態から起こして画面を表示するならば
FLAG_SHOW_WHEN_LOCKED | FLAG_TURN_SCREEN_ON | FLAG_DISMISS_KEYGUARD
で良いようだ。

PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
	| PowerManager.ACQUIRE_CAUSES_WAKEUP
	| PowerManager.ON_AFTER_RELEASE,
	"TimerExample6");
wakeLock.acquire();
// この間、ロックを取得した状態にある
wakeLock.release();

参考ページ:
Y.A.M の 雑記帳: Android PowerManager を使う
画面を ON のままにする方法 - Android 開発入門
液晶パネルのWakeLockを取得し、Sleep状態からWake状態へ遷移する | Tech Booster
スクリーンロックを解除する方法 - 明日の鍵

January 29, 2012

朝日新聞土曜版の「職場の理不尽Q&A」が頭にくる

朝日新聞の土曜版「be on Saturday」に「職場の理不尽Q&A」という職場のことに関する人生相談みたいなコーナーがあるのだが、この回答が毎回毎回とても頭に来る。
どんな質問に対しても、回答の基本姿勢は
「長いものには巻かれましょう」
「出る杭は打たれるよ、静かにしてましょう」
「人のことをとやかく言ってるけど、あなた自身に問題あるんじゃないの?」
だ。

28日のこのコーナーでは、職場はで不正出張をしている人を上司に告発したいという相談に対して
「そんなことしてもあなたが職場にいづらくなるだけですよ。」
「そもそもそんなこと思うなんて、あなた自身に問題あるんじゃないですか?」
とうものだった。
先日、オリンパスが内部通報者に対する重大な人権侵害をしたとして東京弁護士会から警告を受けた。公益通報者保護法が施行されて内部告発した人を保護していこうという世間の流れなのに、朝日新聞は「会社で不正行為を見つけてもだまっとけよ。」という考えらしい。

他に以前の相談で覚えているのは
「やってもやらなくて意味なさそうな仕事をどんどん押し付けられて、忙しすぎて死にそう。」
という相談に対して
「効果なさそうな仕事はやらなきゃいいじゃん」
という回答だった。
相談者はやる・やらいないの決定権を持ってない人で、上から「つべこべ言わずにとにかくやれっ!」って言われてるから困って相談してるんだろう。
なのに上記のような回答。バカじゃなかろうか。

「長いものには巻かれろ」、「出る杭は打たれる」、「見てみぬふり」って日本人の悪いところだと思う。
それを大新聞が助長するようなことを言っている。
なんか悲しくなる。。。

Androidアプリ開発メモ058:ロック画面を出さないようにする

タイマーなどのアプリで画面のバックライトが消えた状態やロック画面からアクティビティを表示する方法を検索すると PowerManager と KeyguardManager を使う例が多く出てくる。
ただ、KeyguardManager.KeyguardLock は現在はdeprecatedになっていて、代わりに windowに WindowManager.LayoutParams の FLAG_DISMISS_KEYGUARD と FLAG_SHOW_WHEN_LOCKED をセットする方法が使うようにドキュメントに書いてある。deprecatedになった KeyguardManager のメソッドや KeyguardManager.KeyguardLock のところに。

フラグをセットした場合の動きを確認するサンプルコード

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);
	
	// フラグをセット
	Button button5 = (Button)findViewById(R.id.button5);
	button5.setOnClickListener(new View.OnClickListener() {
		public void onClick(View v) {
			Window window = getWindow();
			window.addFlags(
				| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
				| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
		}
	});
	
	// フラグをクリア
	Button button6 = (Button)findViewById(R.id.button6);
	button6.setOnClickListener(new View.OnClickListener() {
		public void onClick(View v) {
			Window window = getWindow();
			window.clearFlags(
				| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
				| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
		}
	});
}

上記のコードを実装したボタンがあるだけのアプリは実機(Xperia ray)で次のように動いた。

  1. ボタン5を押す(フラグがセットされる)。
  2. 電源ボタンを押すと、画面のバックライトが消灯する。
  3. 電源ボタンかHOMEキーを押すと、バックライトが点灯しアプリの画面が表示される。
  4. ボタン6を押す(フラグをクリア)
  5. 電源ボタンを押すと、画面のバックライトが消灯する。
  6. 電源ボタンかHOMEキーを押すと、バックライトが点灯しロック画面が表示される。

参考ページによると、「lock pattern」とやらのあり・なしで同じフラグをせっとしてあっても動きが違うようだ。
lock pattern ってのは
設定>現在地情報とセキュリティ>画面ロックの設定>パターン
のことだろうか?

今、AlarmManagerを使って5分とか10分とか間隔を指定すると一定時間毎に画面が表示されて音が鳴るようなアプリを作ろうとしている。
このアプリでは FLAG_DISMISS_KEYGUARD と FLAG_SHOW_WHEN_LOCKED に加えて FLAG_TURN_SCREEN_ON をWindowにセットしている。
FLAG_TURN_SCREEN_ON は自信はないが、たぶん画面が表示されるときにバックライトを点灯するということだと思う。
これでバックライトが消えた状態でも時間が来れば画面が表示される、と思ったが、うまくいかないときもある。画面は真っ暗なままで音だけが鳴る。
表示される場合/表示されない場合の切り分けができていない。

また、フラグとは関係ないかもしれないが、アラームの時間が時々遅れたり、いつまでたってもアラームが来なかったり、いつの間にかアラームがキャンセルされていたりする。原因はどれも不明で未解決。

参考ページ:
Y.A.M の 雑記帳: Android FLAG_DISMISS_KEYGUARD と FLAG_SHOW_WHEN_LOCKED を使う
スクリーンロックを解除する方法 - 明日の鍵
Booster

Androidアプリ開発メモ057:AVDの画面の向きを変更する

Ctrl+F11 または Ctrl+F12 で画面の向きを変更できる。
「Ctrl+F11 で横向き、Ctrl+F12 で縦向き」と書いてあるところもあるが、どちらでも今縦なら横に、横なら縦に向きになる。
それぞれ右回転、左回転ってことだろうか。

実際にAVDで試すと、ホーム画面だとうまく向きが変わってくれる。
しかしアプリだと動きがおかしい。縦から横にしたときは問題ないのだが、横から縦にすると下の画像のようにデバイスは縦画面になるが画面の中が横画面の時のままになる。
何でだろう?

ガンダムAGE第2部、少し見たけど相変わらずひどい #anime

冒頭少し見たけど、ひどすぎるなあ。
第1部から25年たったけど戦争は続いていて、ヴェイガンが徐々に勢力を広げているって、あり得ないだろう。
第1部の頃はヴェイガンの方が技術レベルが高さから優位に立っているのはわかる。しかしあの時点で既に2機だけとはいえガンダムと白い人(ウルフだっけ?)のMSというヴェイガンに対抗できる高性能機があった。
それから25年間あったらガンダムに使われている技術をフィードバックしてヴェイガンのMSに対抗できる量産型MSが作れるだろう。
それにヴェイガンは失敗した火星移民の生き残りで、人口は地球連邦側より遙かに少ないはずだ。ファーストのジオンと同じでマンパワーその他国力で大きく劣るわけだから戦争に勝つには短期決戦しかあり得ない。25年戦い続けて優位を保ってるって論理的におかしい。
SEEDや00はなぜ主人公が強いかとかなぜガンダムが強いかという理由付けがちゃんとあった。
AGEはそういうのが全くない。
子供向けとはいえ、ガンダムを名乗るならもうちょっときちんとした設定を考えべきだったのではないか。


笹本祐一さんが最近のガンダムについてつぶやく - Togetterの内容は非常に納得できるものだ。
ガンダムをラーメンにたとえると、GやWはラーメンかどうかは怪しいが食べてみればおいしい(おいしくないという人も当然いるが)。
しかしAGEはラーメンだとかラーメンじゃないかという以前に、料理にすらなっていないと。

January 28, 2012

2012シーズン新潟始動 #albirex

23日に新体制の発表があり、チームが動き出した。
さて、今シーズンの戦力について考えると戦力ダウンは間違いない。新潟のストロングポイントだったヨンチョルと高徳が抜けて、さらにCBのレギュラー千葉が移籍。ブルロペが残ってくれたのは本当に助かった。
補強は前の方がガンバから平井、韓国の大卒キムヨングン、ブラジルからアラン・ミネイロ。SBに京都から中村、CBに湘南から大井健太郎。
高卒の鈴木武蔵はJ1ですぐ通用するだろうか。素質は間違いなくあると思うから、途中出場でもいいから使って育てて欲しい。

よくわからんのが千葉の穴埋めに大野を戻すのではなく大井を取って、大野は湘南へレンタルしたこと。
これは、新潟は大野は正直J1では厳しいと思っている、大井はJ1でやりたい、湘南は大井の代わりをよこせということでこういう移籍になったのか。
大井は磐田では長年レギュラーCBが出れないときの控え、去年はJ2だったから、J1でレギュラーとしてシーズンを過ごすのは初めてか。奮起を期待しよう。がんばれ大井。

こう見るとJ1で実績あるのは平井だけ。キムヨングンやアラン・ミネイロがチームに早くフィットして活躍してくれれば中位くらいにいけるかもしれないが、そうじゃないと厳しい。
どこぞの「一番早い順位予想」でもことごとく16位以下だった。無理もない^^;

今週のサカダイの特集は「2012 Jリーグ全40クラブの補強診断」。
新潟は編集部の評価がC、柱谷幸一の評価はE。
#5段階評価(A~E)なのか?編集部はEを一つも付けてないが。
編集部の評価が甘い気がする。新潟以外も首をかしげるような評価もある。
たとえばFC東京がD評価になってる。今野の穴は確かに大きいが磐田でレギュラーのCBだった加賀を獲得したし、それ以外のポジションだと新潟が欲しかった千真やアーリアジャスールを取っている。
大物の獲得はないが新潟より下ってことはないと思うけどなあ。

サカダイには予想布陣が載っていた。
ミシュウとブルロペの2トップで平井が左MFになっていたが、ミシェウと平井が逆の可能性もあるだろう。
右MFはアラン・ミネイロだった。こいつの活躍がチームの浮沈を握っているような気がする。
亜土夢は右MFの控え。まあ去年は悪くなかったとはいえすごく良かったわけでもない。FKからの得点も少なかったし、アラン・ミネイロが使えるような控えもやむなしだろう。
ボランチは本間と菊地。まあそうだろうな。やはり菊地はボランチだよ。三門よりいい。小林は年齢的にフルにはできないだろうし。
DFは左SBが中村、CBが大井と大輔。右はSBは村上。
鹿島から取った小谷野は予想布陣のどこにも載っていない。使い道なしってこと?
まあ、神田強化部長を信じるしかないな。
まず今年は「潟る」のをどうにかしないとな^^;

January 27, 2012

PHPメモ009:クラス

Javaのクラスとかなり近い。

  • プロパティ(メンバ変数)、メソッドがある。
  • newでインスタンス化
  • extendsで継承。
  • メンバのアクセス権をpublic,protected,privateで指定する。
  • クラスとメソッドに対してfinalでオーバーライド禁止(プロパティには使用できない)。
  • abstractで抽象化。
  • interfaceとimplements。

クラスの定義

クラス名は大文字小文字を区別しない。

class <クラス名>
{
	<プロパティの定義>
	<メソッドの定義>
}

メンバへのアクセス

static、constで定義しメンバには"::"でアクセスする。
ここでの変数名には先頭の"$"がいる(定数名の方には定数だから "$" は不要)。

<クラス名|self|parent>::<変数名|定数名>

それ以外はのメンバには"->"でアクセスする。
ここでの変数名には先頭の"$"はいらない。

<クラス参照の変数の変数名>-><変数名>

アクセス権の指定

プロパティとメソッドに対するアクセス権はpublic,protected,privateで指定する。 メソッドでアクセス権の指定を省略した場合はpublicとなる。

public どこからでもアクセス可能
protected そのクラス自身、継承したクラス、親クラスからアクセス可能
private そのクラス自身
var publicと同じ。下位互換のためにある。PHP5では使用すべきではない。

親クラスから子クラスのメンバーにアクセスって、どうやるんだろう?

定数(const)

定数はconstを付けて宣言する。定数名には先頭の'$'はいらない。
#変数じゃないってことか。

$this

Javaの"this"と同じ。

self,parent

クラス定義の内部からメンバにアクセスするために使う。
selfはそのクラス自身、parentは親クラス。

コンストラクタ・デストラクタ

void __construct ([ mixed $args [, $... ]] )

下位互換のため __construct() がない場合はクラス名と同じ名前のメソッドがコンストラクタとして探されるが、PHP5では__construct()を使うべき。
子クラスのコンストラクタでは親クラスのコンストラクタは明示的に呼ばれないので"parent::__construct()"が必要。

デストラクタはオブジェクトを参照するものがひとつもなくなったときに呼ばれる。またスクリプトの終了時にも順不同で呼ばれる。

void __destruct ()

クラスのオートローディング

__autoload()関数を定義すると、未定義のクラスが使用され時に__autoload()が実行されてクラスをロードする。

function __autoload($class_name) {
    include $class_name . '.php';
}

サンプルコード

class A1
{
	const constant = 'A1_Constant';
	public static $stat = 'A1_Static';
	
	public    $pub = 'A1_Public';
	protected $pro = 'A1_Protected';
	private   $pri = 'A1_Private';
	
	public    $var1 = 'A1_var';
	
	// コンストラクタ
	public function __construct() {
		echo 'A1 constructor is called.' . "\n";
	}
	
	public function showProperties() {
		echo 'A1 showProperties() is called.' . "\n";
		echo '  constant=' . self::constant . "\n";
		echo '  $stat=' . self::$stat . "\n";
		echo '  $pub=' . $this->pub . "\n";
		echo '  $pro=' . $this->pro . "\n";
		echo '  $pri=' . $this->pri . "\n";
	}
	
	protected function proMethod() {
		echo 'A1 proMethod() is called.'. "\n";
	}
}

class A2 extends A1
{
	public    $var1 = 'A2_var';
	
	// コンストラクタ
	public function __construct() {
		parent::__construct();
		echo 'A2 constructor is called.' . "\n";
	}
	
	public function showProperties() {
		echo 'A2 showProperties() is called.' . "\n";
		echo '  constant=' . self::constant . "\n";
		echo '  $stat=' . self::$stat . "\n";
		echo '  $pub=' . $this->pub . "\n";
		echo '  $pro=' . $this->pro . "\n";
		echo '  $pri=' . $this->pri . "\n";
	}
	
	public function pubMethod() {
		echo 'A2 pubMethod() is called.' . "\n";
		$this->proMethod();
	}
}

echo 'A1::constant=' . A1::constant . "\n";
echo 'A1::$stat=' . A1::$stat . "\n";

$baseClass = new A1();
$baseClass->showProperties();
echo '$baseClass->pub=' . $baseClass->pub . "\n";
echo '$baseClass->var1=' . $baseClass->var1 . "\n";

echo 'A2::constant=' . A2::constant . "\n";
echo 'A2::$stat=' . A2::$stat . "\n";

$subClass = new A2();
$subClass->showProperties();
$subClass->pubMethod();
echo '$subClass->pub=' . $subClass->pub . "\n";
echo '$subClass->var1=' . $subClass->var1 . "\n";

出力

A1::constant=A1_Constant
A1::$stat=A1_Static
A1 constructor is called.
A1 showProperties() is called.
  constant=A1_Constant
  $stat=A1_Static
  $pub=A1_Public
  $pro=A1_Protected
  $pri=A1_Private
$baseClass->pub=A1_Public
$baseClass->var1=A1_var
A2::constant=A1_Constant
A2::$stat=A1_Static
A1 constructor is called.
A2 constructor is called.
A2 showProperties() is called.
  constant=A1_Constant
  $stat=A1_Static
  $pub=A1_Public
  $pro=A1_Protected
  $pri=
A2 pubMethod() is called.
A1 proMethod() is called.
$subClass->pub=A1_Public
$subClass->var1=A2_var

PHPメモ008:include,require

include,require,include_once,require_onceは指定したファイルを読み込んで評価する。
関数・クラスなどを機能ごとにファイルにまとめてモジュールとし、必要に応じて読み込むようにする。

上記4つの言語構造の動作の違いは、指定したファイルがなかった場合、
include,include_onceは警告を発行し処理が続行され、
require,require_onceはエラーを発行して処理が停止される。
また、include_once,require_onceは複数回実行されても1回しか読み込まない。

サンプルコード
module1.php

<?php
echo 'module1';
?>

requireoncetest.php

<?php
require_once 'module1.php';
require_once 'module1.php';
?>
requireoncetest.phpの出力
module1

January 26, 2012

PHPメモ007:スコープ

PHPの変数はほとんどがグローバルスコープ。
CやJavaではブロック内で宣言した変数のスコープはブロック内に限られるが、PHPではブロック内で初めて出てきた変数もグローバルスコープになる。

{
	$a = 10;
}
echo $a;	// 10と出力される

関数では関数内で使用される変数はすべて関数内のみのローカルスコープとなる。

サンプルコード
$a = 10;

function foo() {
	$a = 20;
	
	echo "\$a=${a} in foo()<br />\n";
}

echo "\$a=${a}<br />\n";
foo();
出力
$a=10<br />
$a=20 in foo()<br />

クラス内の変数についてはクラスのところで説明。

global

関数内からグローバルスコープの変数にアクセスしたい場合、globalキーワードを使ってグローバル変数を宣言する。
ただし、可読性が悪くなったりバグの原因になる可能性があるのでやたらめったら使うものではない。というかなるべく使わないほうがいいと思う。

サンプルコード
$b = 30;

function bar() {
	global $b;
	
	echo "global \$b=${b} in foo()<br />\n";
	
	$b = 40;
}

bar();
echo "\$b=${b}<br />\n";
出力
global $b=30 in foo()<br />
$b=40<br />

輪廻のラグランジェ、視聴中止

第3話を見た。
主人公の行動が不可解。
敵は上空にいるだけで町に攻撃を加えているわけじゃないのに、自分から敵につっかかっていって逆にやられて町に落とされてる。
鴨川を守るつもりらしいが、鴨川に被害を与えてるのは主人公じゃん。

それに考え方も嫌な感じだ。
知っている人の畑に落下したときは悪いと思ったようだが、空き家や公共物を壊してもまったく悪いと思っていないらしい。
人が住んでいなくてもその家の所有者には被害を与えているわけだし、公共物は市民の共有財産だ。それを壊してもなにも感じないと言うのはどうなんだろう。
監督とか脚本書いている人がそういう考えの持ち主なんだろうな。

2話までは面白くないだけだったが3話で不快な気分になったので、この作品見るのはここまで。
OP歌とかメカデザインは嫌いじゃなかったのに、残念だ。

January 25, 2012

robocopyでバックアップ

robocopyについては以前ブログに書いたつもりだったのだが、検索しても出てこないので書いてなかったようだ。
PCのデータをバックアップするのにrobocopyというコマンドが使える。GUIのバックアップツールなんかよりシンプルで使いやすい。
robocopyはフォルダを同期を取るためのコマンドで、Vistaと7では標準で入っているが、XPではリソースキットをインストールする必要がある。
バッチファイルを作ってスタートメニューに登録するなり、タスクにして定期的に実行するなりすればよい。

例:c:\dataをコピー元、g:\backup\dataをコピー先として同期する。

robocopy c:\data g:\backup\data /mir

参考ページ:robocopyでフォルダをバックアップ/同期させる - @IT

#FF11 アビセアNMソロ1勝2敗

アートマ、ジェイド目当てでアビセアNMにシ/踊で挑んだ。1勝2敗orz

Npfundlwa(ミザレオ、ウサギ)
トリガ:黒兎の尻尾
ジェイド:強運の蒼色ジェイド
一撃のダメージが300以上で、命中は結構高い。
回復が間に合わずに敗北。


Tuskertrap(ミザレオ、フライトラップ)
トリガ:飛行植物の斑葉
ジェイド:癒しの蒼色ジェイド
サペリフィックの睡眠はダメージを受けても起きない。それを食らって死亡。


Kampe(アットワ、サソリ)
トリガ:不浄な鋭爪
アートマ:金爪のアートマ
相当避けられる。後半は範囲攻撃連続モードになったが、なんとか耐えて倒したが赤弱点は突けず。ルシドエーテル1を使用。

January 24, 2012

PHPメモ006:関数、言語構造

関数の定義

function <関数名>(<引数のリスト>)
{
    <処理>
    
    return <戻り値>;
}

引数をとる必要がない関数ならば引数はなくてもかまわない。
returnは値を返さない関数の場合は省略できる。

デフォルト引数

引数にデフォルトの値をセットしておくこともできる。

function foo($arg = null)
{
    ...
}

引数の値渡しと参照渡し

関数の引数に変数を渡す場合、

foo($var);

のようにそのまま変数を関数に渡すのは値渡しで、関数側で受け取った値を変更しても呼び出し元に影響しない。
対して、

foo(&$va);

のように変数の前に&を付けた場合は参照渡しとなり、関数側で受け取った変数を変更すると呼び出し元でもその変数の値が変わる。

また、関数を以下のように宣言すると常に参照渡しとなる。

function foo(&$param)
{
    ...
}

値渡し・参照渡しのサンプルコード。

function func1($arg) {
	$arg = $arg + 1;
}

function func2(&$arg) {
	$arg = $arg + 1;
}

$var1 = 10;
$var2 = 20;
$var3 = 30;

// 関数呼び出し前
echo "${var1},${var2},${var3}<br />\n";

func1($var1);
func1(&$var2);
func2($var3);

// 関数呼び出し後
echo "${var1},${var2},${var3}<br />\n";

実行結果

10,20,30<br />
10,21,31<br />

言語構造

以下の命令は関数呼び出しのような書き方はできるが関数ではなくて言語構造。関数呼び出し風の書き方は推奨されない。
echo出力する
empty文字列変数に値が設定されているか判定する
exit処理の終了
include他のファイルを読み込む
isset変数に値が設定されているか判定する
print出力する
require他のファイルを読み込む
return関数から戻る
unset変数の値をクリアする

Androidアプリ開発メモ056:AlarmManager

関連する以前の記事:
TimerとTimerTaskで一定時間毎に処理をする
Androidアプリ開発メモ038:AppWidget その4:AppWidgetのボタンの識別(ペンディングインテントについての記事)

何らかのアクションをスケジューリングする実装についてTimerとTimerTaskを使ったやり方について以前記事を書いたが、AlarmManagerを使ってもできる。
TimerとTimerTaskはJavaの標準ライブラリに含まれているが、AlarmManagerはパッケージがandroid.app.AlarmManagerでありAndroid独自のクラスである。

AlarmManagerはAndroidシステムのアラームサービスへのアクセスを提供する。
AlarmManagerに時間、間隔とペンディングインテントをセットしてアクティビティの開始|サービスの開始|インテントのブロードキャストをスケジューリングする。
アラームをセットするにはset()、setRepeating()、setInexactRepeating()を使用する。

public void set(int type, long triggerAtTime, PendingIntent operation)
指定した時間にアラームをセットする。
引数
 type  ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC, RTC_WAKEUPのどれか1つ
 triggerAtTime  アラームが作動する時間
 oepration  アラームが作動した時に実行するアクション

public void setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
繰り返しアラームをスケジュールする。
引数
 interval アラームのその後の繰り返しの間隔

public void setInexactRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
不正確なアラームをスケジュールする。電力効率がsetRepeating()より良い。

引数typeに指定する定数の意味は以下。

定数意味
ELAPSED_REALTIME アラームの時間にSystemClock.elapsedRealtime()(スリープ中を含むシステムが起動してからの時間)を使う。スリープ中にタイマーが作動してもデバイスを起こさない。
ELAPSED_REALTIME_WAKEUP アラームの時間にSystemClock.elapsedRealtime()(スリープ中を含むシステムが起動してからの時間)を使う。スリープ中にタイマーが作動したらデバイスを起こす。
RTC アラームの時間にSystem.currentTimeMillis()(UTCの実時間)を使う。スリープ中にタイマーが作動してもデバイスを起こさない。
RTC_WAKEUP アラームの時間にSystem.currentTimeMillis()(UTCの実時間)を使う。スリープ中にタイマーが作動したらデバイスを起こす。

アラームのキャンセルにはcancel()を使用する。

public void cancel(PendingIntent operation)
マッチしたインテントでアラームを削除する。

コード例。ボタン1はset()、ボタン2はsetRepeating()を呼ぶ。onDestroy()でsetRepeating()でセットしたスケジュールをキャンセルする。

@Override
public void onClick(View v) {
	String tag = (String)v.getTag();
	Log.v("TEST", "Activity:onClick():tag=" + tag);
	
	Intent intent = null;
	// ボタン1の処理
	if (tag.equals("button1")) {
		// アクションをセット
		intent = new Intent("com.example.alarmmanager.TEST");
		intent.putExtra("key", "A");
		
	// ボタン3の処理
	} else if (tag.equals("button2")) {
		// アクションをセット
		intent = new Intent("com.example.alarmmanager.TEST");
		intent.setData(Uri.parse("http://xxx"));
		intent.putExtra("key", "B");
	}
	
	// PendingIntentの作成
	PendingIntent pendingIntent
		= PendingIntent.getBroadcast(
				this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
	
	long currentTime = System.currentTimeMillis();
	// エディットテキストから秒を取得
	int intervalSec = Integer.parseInt(((EditText)findViewById(R.id.editText1)).getText().toString());
	long intervalMSec = intervalSec * 1000L;	// 変換(秒=>ミリ秒)
	Log.v("TEST", "Activity:onClick():currentTime=" + currentTime + " intervalMSec=" + intervalMSec);
	
	// AlarmManagerにPendingIntentをセット
	if (tag.equals("button1")) {
		// intervalMSecミリ秒後に起動
		alarmManager.set(AlarmManager.RTC_WAKEUP, currentTime + intervalMSec, pendingIntent);
	} else if (tag.equals("button2")) {
		// intervalMSecミリ秒後に1回目、それからintervalMSecミリ秒間隔
		alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, currentTime + intervalMSec, intervalMSec, pendingxIntent);
		Log.v("TEST", "Activity:onClick():setRepeaint() execute.");
	}
}

@Override
protected void onDestroy() {
	super.onDestroy();
	
	// キャンセル
	Intent intent = new Intent("com.example.alarmmanager.TEST");
	intent.setData(Uri.parse("http://xxx"));
	PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
	alarmManager.cancel(pendingIntent);
}

参考ページ:
AlarmService を利用したサービス実行のスケジューリング - Android 開発入門
AlarmManager - 愚鈍人

January 23, 2012

2作品視聴中視 #anime

録画したアニメを見るのが追いつかなくて貯まってきた。
録画予約を確認したら、
日:HUNTER×HUNTER、輪廻のラグランジェ、アクエリオンEVOL
水:Another
木:へうげもの、テルマエ・ロマエ、ハイスクールD×D
金:ペルソナ4 THE ANIMATION、LAST EXILE 銀翼のファム
土:バクマン、偽物語、灼眼のシャナ

12本。
そりゃ見きれないわw

で、「ペルソナ4」と「ハイスクールD×D」の録画予約をキャンセル。
「ペルソナ4」は、ゲームのペルソナシリーズをそこそこやってきたのでアニメも見ていたが、正直、そんなに面白くない。
「ハイスクールD×D」は、この手の作品を見たことなかったのでとりあえず見てみたけど、続きが気になるような話じゃなかったし。

あと、「テルマエ・ロマエ」と「へうげもの」は今週で終わり。

これで2月からは8作品に減る。
週8本なら貯めずに見れるだろう。

January 22, 2012

Androidアプリ開発メモ055:ブロードキャストレシーバ その2:インテントフィルタ

ブロードキャストレシーバ、Intentの以前の記事:
Androidアプリ開発メモ014:Intentその2
Androidアプリ開発メモ020:ブロードキャストレシーバ

以前のブロードキャストレシーバに関する記事があまりにても簡素すぎたので、もうちょっと詳しく。
暗黙インテントを受信するブロードキャストレシーバとインテントフィルタの設定について。

内部クラスとしてブロードキャストレシーバ(privateとpublic static)を持つアクティビティのコード
package com.example.broadcastreceiverexample;

import java.util.Set;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.PatternMatcher;
import android.util.Log;

public class BroadcastReceiverExample extends Activity {
  
  private BroadcastReceiver receiver;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    // ブロードキャストレシーバの作成、登録
    receiver = new InnerReceiver1();
    IntentFilter intentFilter = new IntentFilter("jp.aabb.ACTION_A");
    intentFilter.addDataScheme("http");
    intentFilter.addDataAuthority("aabb.jp", null);
    intentFilter.addDataPath("/abc.txt", PatternMatcher.PATTERN_LITERAL);
    intentFilter.addCategory("jp.aabb.CATEGORY_1");
    registerReceiver(receiver, intentFilter);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    
    // ブロードキャストレシーバの登録を解除
    unregisterReceiver(receiver);
  }

  public static void logv(String prefix, Intent intent) {
    String action = intent.getAction();
    Uri data = intent.getData();
    Set<String> categories = intent.getCategories();
    Log.v("TEST", prefix
        + ":act=" + action 
        + " dat=" + ((data == null) ? "" : data.toString())
        + " cat=" + ((categories == null) ? "" : categories.toString()));
  }
  
  /** privateな内部クラスのブロードキャストレシーバ */
  private class InnerReceiver1 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
      logv("InnerReceiver1#onReceive()", intent);
      
      // ここに実行した処理を記述
    }
  }
  
  /** public staticな内部クラスのブロードキャストレシーバ */
  public static class InnerReceiver2 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
      logv("InnerReceiver2#onReceive()", intent);
      
      // ここに実行した処理を記述
    }
  }
}
publicなブロードキャストレシーバのコード
package com.example.broadcastreceiverexample;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PublicReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    BroadcastReceiverExample.logv("PublicReceiver#onReceive()", intent);
    
    // ここに実行した処理を記述
  }
}
AndroidManifest.xmlのブロードキャストレシーバの設定部分
<receiver android:name=".BroadcastReceiverExample$InnerReceiver2">
  <intent-filter>
      <action android:name="jp.aabb.ACTION_A" />
      <action android:name="jp.aabb.ACTION_B" />
  </intent-filter>
</receiver>

<receiver android:name=".PublicReceiver">
  <intent-filter>
    <action android:name="jp.aabb.ACTION_A" />
    <data android:scheme="http" android:host="aabb.jp" /> 
  </intent-filter>
  <intent-filter>
    <action android:name="jp.aabb.ACTION_B" />
    <data android:scheme="http" android:host="aabb.jp" />
    <category android:name="jp.aabb.CATEGORY_1" /> 
  </intent-filter>
</receiver>

InnerReceiver1はprivateなクラスなので、AndroidManifest.xmlに記述するのではなく25~31行目のようにインテントフィルタと一緒にContext#registerReceiver()で登録する。
登録したレシーバはアプリケーションが終了するまでに適当なタイミングでContext#unregisterRecieverで登録解除しなければならない。上記のアプリの場合はonDestroy()の中で登録解除している(39行目)。

InnerReceiver2とPublicReceiverはpublicなクラスなので、AndroidManifest.xmlにreceiver要素で書いておく。

インテントフィルタの設定

上記のコードのブロードキャストレシーバについて、インテントフィルタの設定と受信できるインテントについて表にまとめた。

A055

「act=A」はアクションが"jp.aabb.ACTION_A"、cat=1はカテゴリが"jp.aabb.CATEGORY_1"という意味で、そのインテントを受信できる場合は○とした。

アクションが列挙されている場合、インテントのアクションが列挙されたアクションのどれかに一致すればフィルタを通過する。
表のInnerReceiver2では、アクションが"jp.aabb.ACTION_A","jp.aabb.ACTION_B"のどちらでもフィルタを通過する。

データはスキーマとホストだけ設定されている場合はパスは何であってもフィルタを通過する。
パスまで指定されいている場合はパスまで一致する場合にフィルタを通過する。
表のPublicReceiverでは、1個目のフィルタにスキーマ="http"、ホスト="aabb.jp"が設定されているので、データが "http://aabb.jp"、"http://aabb.jp/abc.txt"、"http://aabb.jp/xxx.txt" のどれでも通過する。
InnerReceiver1では、スキーマ="http"、ホスト="aabb.jp"、パス="/abc.txt"なので、データが "http://aabb.jp/abc.txt" はフィルタを通過するが、"http://aabb.jp" や "http://aabb.jp/xxx.txt" はフィルタを通過しない。

カテゴリーが列挙されている場合、インテントのカテゴリすべてがフィルタに列挙されているカテゴリと一致した場合にフィルタを通過する。
表のInnerReceiver1では、フィルタにはカテゴリ"jp.aabb.CATEGORY_1" が設定されているので、カテゴリが "jp.aabb.CATEGORY_1"だけのインテントはフィルタを通過するが、"jp.aabb.CATEGORY_1" に加えて "jp.aabb.CATEGORY_2" を持つインテントはフィルタを通過できない。

Androidアプリ開発メモ054:Intent その3:コマンドラインからAVDにIntentを投げる

Intentの以前の記事:
Androidアプリ開発メモ014:Intentその2

"adb shell am"でコマンドラインからAVDにIntentを投げることができる。
インテントを受信するアプリの動作確認に便利。いちいちテスト用のインテントを投げる処理を実装しなくて済むので。
下記はコマンドのヘルプ表示。アクティビティ開始、サービス開始、ブロードキャストはそのままだと思うが、他はよくわからない。

usage: am [subcommand] [options]

    start an Activity: am start [-D] [-W] <INTENT>

        -D: enable debugging
        -W: wait for launch to complete

    start a Service: am startservice <INTENT>

    send a broadcast Intent: am broadcast <INTENT>

    start an Instrumentation: am instrument [flags] <COMPONENT>

        -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
        -e <NAME> <VALUE>: set argument <NAME> to <VALUE>
        -p <FILE>: write profiling data to <FILE>
        -w: wait for instrumentation to finish before returning

    start profiling: am profile <PROCESS> start <FILE>

    stop profiling: am profile <PROCESS> stop

    start monitoring: am monitor [--gdb <port>]

        --gdb: start gdbserv on the given port at crash/ANR


    <INTENT> specifications include these flags:

        [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
        [-c <CATEGORY> [-c <CATEGORY>] ...]
        [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
        [--esn <EXTRA_KEY> ...]
        [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
        [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
        [-n <COMPONENT>] [-f <FLAGS>]
        [--grant-read-uri-permission] [--grant-write-uri-permission]
        [--debug-log-resolution]
        [--activity-brought-to-front] [--activity-clear-top]
        [--activity-clear-when-task-reset] [--activity-exclude-from-recents]
        [--activity-launched-from-history] [--activity-multiple-task]
        [--activity-no-animation] [--activity-no-history]
        [--activity-no-user-action] [--activity-previous-is-top]
        [--activity-reorder-to-front] [--activity-reset-task-if-needed]
        [--activity-single-top]
        [--receiver-registered-only] [--receiver-replace-pending]
        [<URI>]

実行例:インテントをブロードキャスト
C:\Program Files\Android\android-sdk\platform-tools>adb shell am broadcast -a jp.hogehoge.ACTION_A -d http://hogehoge.jp/abc.txt -c jp.hogehoge.CATEGORY_1
Broadcasting: Intent { act=jp.hogehoge.ACTION_A cat=[jp.hogehoge.CATEGORY_1] dat=http://hogehoge.jp/abc.txt }
Broadcast completed: result=0
C:\Program Files\Android\android-sdk\platform-tools>

January 20, 2012

2012年1月開始アニメ第1話感想 #anime

第1話を録画したのは「キルミーベイベー」、「偽物語」、「輪廻のラグランジェ」、「アクエリオンEVOL」、「Another」、「ハイスクールD×D」。
継続して意見るつもりはないが、気になった作品として「ガンダムSEED HD REMASTER」、「モーレツ宇宙海賊」にも一言。

キルミーベイベー
4コママンガを忠実にアニメしたような感じ。5分10分ならいいけど30分はつらい。同じ4コママンガが原作の「ひだまりスケッチ」や「けいおん!」はうまく話をつなげていて30分飽きることなく見れるんだけど、この差はアニメのスタッフの力量の差なんだろうか。
CVはソーニャ役の田村睦心や新井里美、チョーあたりは結構好きなんだが、それでも継続してみる気はしない。という訳で、視聴中止。

田村睦心は「生徒会役員共」のWEBラジオに出てなかなかに面白い人だったので結構好きなんだけど、同じ声質の声優として上に朴ロ美と小林ゆうがいるから大変だよな^^;

傷物語
安心して見られる。
冒頭から良くわからない状況で囚われの阿良々木さん。謎が深まる。そしてBパートでは変態っぷりで笑わせてくれる阿良々木さん。たのしいなあw
忍のCVは坂本真綾か。意外。最近は女性キャラクターをやる場合はお姉さんとか結構年上の役が多いのに。というか幼女役は珍しいのでは。実際は幼女違うけど。

輪廻のラグランジェ
日産がロボのデザインをしたというので話題のアニメ。
ロボット、格好いいんじゃないでしょうか。「河森さんがデザインしました。」と言われれば信じてしまいそう。ただ、背部というか肩の後ろから伸びている部分、推進器なのかスタビライザーなのか良くわからんが激しい戦闘したらポッキリ折れそうだw
あれで第1話じゃバックドロップしてたがだいじょぶかww
女子高が舞台で女の子がいっぱい。敵は美少年。まあなんというか、基本を抑えている。けどいろんなところで既視感が。目新しい感じはない。
それなりに当たりそうだけど大当たりはしそうにない感じ。

総監督が佐藤竜雄。ムリョウやステルヴィアは好きなので期待したいところだが、肩書きが「監督」じゃなくて「総監督」というのに不安を覚える。
「モーレツ宇宙海賊」の方は監督で、2作品同時に面倒みていることになる。こっちの作品は実質的に「ストーリー原案」とか「監修」じゃないのかと思えてしまう。さて、どうなんだろう。
OP、EDの歌は中島愛。マクロスFの印象が強すぎてそれ以降はイマイチ活躍できてないような気がするが、この作品のOP歌はいいと思います。

アクエリオンEVOL
人類はあと1万2000年も文明を保ったまま生き残っているという設定にまず驚いたw
#実際は100年もたないと自分は思っている。絶滅はしないだろうけど、資源の枯渇や自然環境の変化のために人口はがっつり減って、文明レベルは落ちていくだろう。
絵柄はずいぶん眼が大きくなって萌え系というか記号的になった気がするけど、内容的には実にアクエリオンらしい内容w初回に第1話と第2話を続けて放送したり、宣伝番組をやったりとずいぶんお金をかけている。
前作と違って最初からパチンコメーカーがスポンサーについているだけはある。

Another
原作が「館シリーズ」の綾辻行人で、キャラクターデザイン原案がいとうのいぢ、アニメーション製作がP.A.WORKS。自分が好きな原作者、スタッフなのでで期待したいところだが。。。
監督が「BLOOD C」の水島努というのは不安。あれは昨年見たアニメでダントツのワースト1だった。
まあ第1話見た限りでは問題なかったので、このまま行ってほしい。」

ハイスクールD×D
この手のお色気アニメって毎期1,2作品はあるが、まともに見るのは初めてだ。
あのマークがDVDだと取れるのねw
アニメオリジナル作品かと思ってたらラノベ原作。ラノベって守備範囲広いなあw

そういえばヒロイン役の日笠陽子、先日、夜中にEテレを見てたら高校講座書道の再放送やってて出演していた。
ポーズ付けて「がんばるぞ!」とかやってて、かわいかったけどちょっと痛いなとも思ったw

SEED HD REMASTR
見たのは第2話だけど、絵がきれいだ。
「HD REMASTR」というのはうまいこと上下を削って16:9にしてアップコンバートかけているだけだと思っていたので、
「アップコンバートでこんなにきれいになるのか」
と驚いていたら、新規作画が相当あるらしい。もう別物じゃんw
お金かけてるなあ。回収できるのか?

モーレツ宇宙海賊
タイトルとか雰囲気が古臭い昭和の香りがする。と思ったら原作が笹本祐一。
懐かしい名前だw

2011年12月終了アニメ感想 #anime

もう1月も後半なのに今更感想。
「ペルソナ4」は終わるんだと思ってたら、続いたので驚いた。
「続きは春に発売のPSVita版で」っていう終わりを予想していたのだが。
「Fate/Zero」は終了なくて中断だよな。

UN-GO
いやー、面白かった。劇場版見に行くほどに引き込まれた。去年見たアニメで上位3作品選べといわれればは「まどかマギカ」、「TIGER & BUNNY」とこの作品を選ぶ。あと、豊崎愛生ってさほどいい声優だと思ってなかったが、この作品で見直した。

映画見に行ったときの記事:UN-GO 因果論

WORKING'!!
なんも考えず楽しく見れた。ぽぷらの「ちっちゃくないよ!」ってのがかわいいw原作はまだ続いているからアニメ3期も期待したい。

January 14, 2012

Androidアプリ開発メモ053:サウンドファイルの再生の注意

サウンドファイル再生の以前の記事:
Androidアプリ開発メモ040:サウンドファイルの再生

サウンドファイルを再生を実装したときの失敗をメモ。

ちゃんと解放する

音とトーストを出そうと思って以下のようなコードを書いた。

player = MediaPlayer.create(context, R.raw.sound01);
player.start();

Toast myToast = Toast.makeText(
    context, "COMPLETE", Toast.LENGTH_SHORT);
myToast.show();

これだとリソースを解放していない。どこかで解放してやらねば。

解放するタイミング

リソースを解放する処理を書き足した。

player = MediaPlayer.create(context, R.raw.sound01);
player.start();

Toast myToast = Toast.makeText(
    context, "COMPLETE", Toast.LENGTH_SHORT);
myToast.show();

player.release();
player = null;

しかし、動かしてみると実機では音がでない。エミュレータだと一瞬再生されるから直後のトーストの処理が再生を妨げてるのかと思い、トーストの処理をサウンド再生の前に持っていったが現象は変わらず。
それはそうだ。再生の終了を待たずにリソースを解放してるんだからw
正しくは、サウンドの再生が終わってから解放するように下記のようにする。

player = MediaPlayer.create(context, R.raw.sound01);
player.start();
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  @Override
  public void onCompletion(MediaPlayer mp) {
    player.stop();
    player.setOnCompletionListener(null);
    player.release();
    player = null;
  }
});

Androidアプリ開発メモ052:USB接続した端末を外す

PCとUSB接続した端末を外そうと思い、タスクバーの「ハードウェアの安全な取り外してメディアを取り出す」のインジケーターから「<デバイス名>の取り出し」を選ぶと、

プログラムが'Sony Ericsson xxnnnn ADB Interface Driver'デバイスをまだ使用しているため、デバイスを停止できません。デバイスを使用していると思われるプログラムを閉じてから、再試行してください。

という警告が出て取り外せない。
eclipseや関係ありそうなものを全部終了しても同じ。

端末を取り外すにはコマンドプロンプトで

adb kill-server

とすればよい。
adbサーバを終了させるということらしい。

関連する以前の記事:Androidアプリ開発メモ043:Logcatにアプリのログが出なくなった

SyntaxHighlighter導入

WEBサイトでコードが行番号付きできれいに表示されているのを見て、
「これどうやってるんだろう?自分でCSSを書いているのかな」
と思っていたが、SyntaxHighlighterという便利なものがあるのを昨日知った。

というわけで、こちらのサイトを参考に導入した。
最初、思ったとおりに表示されなくて少し困ったが、自分でcodeタグに独自のスタイルをセットしていたのが原因だった。その独自のスタイル設定を除去したら問題なく表示されるようになった。
それからちょっとカスタマイズ。文章とSyntaxHighlighterを使ったコードの背景色がどちらも白で見分けがつきにくいので、コードの方の背景色を青系の色に変えた。さらに見やすいように1行ごとに互い違いになるようにした。

SyntaxHighlighterのこと、ネットにコードを晒すならもっと早く知っておくべきだった^^;

参考ページ:
ココログフリーに「SyntaxHighlighter(3.0.83)」を導入してみた: アクアマンの『ずくなし』ブログ
syntaxhighlighterの背景色を互い違いにする|ブラックバスを引っ張り出せ!

January 13, 2012

PHPメモ005:配列

PHPの配列はCやJavaの配列とは違い、添え字(インデックス)に整数だけではなく文字列も使える。順番もなんでもいい。
ようするに配列というより連想配列、Javaで言うなら順序付きMap(LinkedHashMap)だ。
以後、添え字をキーと呼ぶ。

キーを省略して初期化すると、キーは自動的に0,1,2,…となる。

array()を使えば複数の要素を一度に初期化できる。

foreachで要素を順番に処理できる。

コード

echo "<pre>\n";

// キーを省略
$array1[] = "a";
$array1[] = "b";
$array1[] = "c";
print_r($array1);

// array()で初期化、キー省略
$array2 = array("子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥");
print_r($array2);

// array()で初期化、キーあり
$array2 = array(1 => "柏", 2 => "名古屋", 3 => "G大阪");
print_r($array2);

// 添え字の値と配列の順序は関係ない。配列の順序は値をセットした順序。
$array3[7203] = "トヨタ自動車";
$array3[6594] = "日本電産";
$array3[3402] = "東レ";
print_r($array3);

// foreachですべての要素を処理する(値のみ)
foreach ($array2 as $val) {
	echo "(${val}) | ";
}
echo "\n";

// foreachですべての要素を処理する
foreach ($array3 as $key => $val) {
	echo "(${key}, ${val}) | ";
}
echo "\n";
echo "</pre>\n";

出力
<pre>
Array
(
    [0] => a
    [1] => b
    [2] => c
)
Array
(
    [0] => 子
    [1] => 丑
    [2] => 寅
    [3] => 卯
    [4] => 辰
    [5] => 巳
    [6] => 午
    [7] => 未
    [8] => 申
    [9] => 酉
    [10] => 戌
    [11] => 亥
)
Array
(
    [1] => 柏
    [2] => 名古屋
    [3] => G大阪
)
Array
(
    [7203] => トヨタ自動車
    [6594] => 日本電産
    [3402] => 東レ
)
(柏) | (名古屋) | (G大阪) | 
(7203, トヨタ自動車) | (6594, 日本電産) | (3402, 東レ) | 
</pre>

TimerとTimerTaskで一定時間毎に処理をする

Androidで一定時間ごとに同じ処理を繰り返すにはどうするか調べていて、TimerとTimerTaskを使う方法を見つけた。
これらのクラスはAndroid独自のものではなく、Javaの標準ライブラリにあるクラスだった。知らんかった^^;

繰り返し処理だけでなく、Timer#schedule()とTimer#scheduleAtFixedRate()で以下のようなさまざまなパターンのスケジュールを指定できる。

  • 指定時間に1回だけ実行。
  • 指定時間に開始し、「固定遅延実行」を繰り返す。
  • 指定した遅延の後に1回だけ実行。
  • 指定した遅延の後に開始し、「固定遅延実行」を繰り返す。
  • 指定時間に開始し、「固定頻度実行」を繰り返す。
  • 指定した遅延の後に開始し、「固定頻度実行」を繰り返す。
実装は以下のようにする。
  • TimerTaskのサブクラスを実装し、繰り返したい処理をrun()に記述する。
  • Timer#schecuel()に上記のTimerTaskのサブクラスのインスタンス、スケジュールに関するパラメータを渡して呼び出す
schedule()とscheduleAtFixedRate()の違いなど詳細は参考ページを参照。

指定した時間毎にトーストを出すAndroidアプリのコード(抜粋)。
アクティビティのコード。

public class TimerExample2 extends Activity {
  
  private long repeatInterval;  // 繰り返しの間隔(単位:msec)
  
  Timer timer;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    final EditText editText1 = (EditText)findViewById(R.id.editText1);
    
    // タイマー開始ボタンの処理
    Button button1 = (Button)findViewById(R.id.button1);
    button1.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        // タイマーをセット
        timer = new Timer();
        TimerTask timerTask = new Task1(TimerExample2.this);
        timer.scheduleAtFixedRate(timerTask, repeatInterval, repeatInterval);
        
        // トーストでタイマー開始を通知
        Toast toast = Toast.makeText(TimerExample2.this, R.string.timer_start, Toast.LENGTH_LONG);
        toast.show();
      }
    });
    
    // タイマー停止ボタンの処理
        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        cancelTimer();
      }
    });
  }

  /**
   * 終了処理
   */
  @Override
  protected void onDestroy() {
    super.onDestroy();
    
    cancelTimer();
  }
  
  /**
   * タイマーをキャンセルする。
   */
  private void cancelTimer() {
    if (timer != null) {
      timer.cancel();
    }
  }
}
スレッドのコード
public class Task1 extends TimerTask {
  
  private Handler handler;
  private Context context;
  
  public Task1(Context context) {
    handler = new Handler();
    this.context = context;
  }
  
  @Override
  public void run() {
    // Viewの操作だけじゃなくてトーストを出すのにもHandler使わないといけないのか。。。
    handler.post(new Runnable() {
      @Override
      public void run() {
        // トーストを出す。
        Toast myToast = Toast.makeText(
            context, "Hello, How are you?",
            Toast.LENGTH_SHORT);
        myToast.show();
      }
    });
  }
}

参考ページ: @IT:Java TIPS -- Javaのタスクを定期的に実行する
Androidで周期的な処理をするクラスを作ってみた « 煩悩の確率論
繰り返し処理を行うとき - Android 開発入門
開発の日誌 タイマーの設定

スウェットのズボンのゴム交換

前記事で100円ショップで買い物、調味料シェイカーと他にスウェットのズボン用のゴムも買った。
寝る時に来ているスウェットのゴムがゆるゆるになっていた。
紐で縛ればずり落ちなくなるが、トイレでいちいち紐をほどくのが面倒なのでゴムの交換に挑戦。

非常に手間取った。
新しいゴムをズボンに通す方法を検索したら
「古いゴムを外に出して一端に新しいゴムを結んで他方の端を引っ張る」
というのがあったのでやってみたが、失敗した。
太いゴム同士を固結びすると、結束力が弱い上に結び目が大きく、ズボンのゴムを通す穴の中で引っかかる。強く引っ張ったら結び目がほどけたorz
試行錯誤してなんとか交換したが2時間近くかかった。

いつかまた自分でズボンのゴムを交換することがあるかもしれないので(あるかな?w)、そのときのためのメモ。
・ゴムは太いものの方が長持ちするかもしれないが、ズボンに通すのは細いものほど通しやすい。細めの方がおすすめ。
・ゴムは先に切らないで元の長さ(1.5m?)のままでズボンに通す。通してから必要な長さに切る。切るときはゴムの両端を縫いつける縫い代の考慮を忘れずに。
・今回は下図のようなものを作ってズボンのゴムの穴に新しいゴムを通した。左の楕円の物体は今回はアドエス付属のスタイラスを使った。右はゴムで端を二つ折り。ゴムを綿の糸で固く縫って、糸の一端をスタイラスに固く結んだ。スタイラスを掴んでズボンのゴムの穴を少しずつ前進させていってゴムを通した。スタイラスの部分は同じくらいの大きさでなめらかな形のものなら何でもいい。安全ピンなら直接ゴムと繋げられるし最適だと思う。
Gom

・試してはいないが、古いゴムと新しいゴムを結んで引っ張る方法の場合、固結びするのではなく糸で縫ったらいいのではないだろうか。縫った部分が小さいので固結びの結び目と違って引っかからないような気がする。
・どの方法にしても、一気にゴムを通すことは出来ない。少しずつ慎重にやること。

January 12, 2012

プロテインシェイカーの代わり

プロテインは結構溶けにくい。
今までプロテインを飲むときにマグカップに入れて箸でかき混ぜていたのだが、プロテインシェイカーがあった方がいいなという気が最近してきた。
でも蓋が付いたプラスティックのコップに400円以上出すのはもったいない気もした。
ブライトとかクリープとかの瓶をプロテインシェイカー代わりに使っているというのをどこかのブログで読んだが、自分はコーヒーを飲まないのでそういう適当な瓶がない。
#そもそもああいうコーヒーに入れるものやミロみたいな水に溶かして飲む飲料って、瓶で売ってる?最近は袋入りしか見かけないけど。

で、100円ショップで代わりになるものはないかと探してみた。
2つ候補があがった。大きめの蓋付きのガラス瓶と「調味料シェイカー」。
ガラス瓶は大きさ、形は理想的な感じだったが、ガラスなので割れるのが心配だ。なにせ激しく振るので間違って飛んでいったら大惨事だ。
調味料シェイカーはブラスチックなので割れる心配はなさそうだが、形が細長くて洗うのが多少面倒そう。
検討した結果、調味料シェイカーにした。
それがこれ。

Choumiryoushaker

実際使ってみると、プロテインシェイカーとして問題なく使用できた。
蓋をきちっと閉めれば激しく振っても漏れがない。
50cc毎にメモリが付いているのもいい。
形状のせいで多少洗いにくいのは確かだが許容できる範囲だ。
いい買い物をした。

January 10, 2012

Androidアプリ開発メモ051:Handler その2:handleMessage()

Handlerについての以前の記事・関連記事:
Androidアプリ開発メモ018:Handler
Androidアプリ開発メモ033:サービス その5:Messengerを使用したバインドされたサービス

HandlerはスレッドからGUIを操作するためのものということではなく、Messageと組み合わせて使う汎用的なプロセス間通信の仕組みなんだろうか?

以前の記事でHandler#post()を使ってメインスレッドではないスレッドからUIを操作する方法を示したが、handleMessage()とsendMessage()、sendEmptyMessage()を使った方法もある。
sendMessage()、sendEmptyMessage()を呼ぶと、Handlerを作成したスレッドにおいてhandleMessage()で送ったMessageが受信される。
Handlerのコンストラクタで

mQueue = mLooper.mQueue;
という部分があるが、これはコンストラクタを実行しているスレッドのメッセージキューの参照をハンドラに渡している。これによってHandlerからHandlerのコンストラクタを実行したスレッドへメッセージを送れるようになる(記事末の参考ページ3参照)。

android.os.Hanlderクラス
public final boolean sendMessage(Message msg)
現在の時刻の前にすべての保留中のメッセージの後に、メッセージキューの最後にメッセージをプッシュします。送ったメッセージはこのハンドラに結び付けられたスレッドで、handleMessage()で受信されます。

戻り値 メッセージがメッセージキューに置かれた場合true

public final boolean sendEmptyMessage(int what)
whatの値だけを持つMessageを送る。

Messageについての詳細はAndroidアプリ開発メモ033を参照。

コード例
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      String text
        = String.format("change text by sendMessage()→handleMessage(). what=%d", msg.what);
      textView1.setText(text);
    }
  };
  
  textView1 = (TextView)findViewById(R.id.textView1);
  
  // postDelayed()を使用する処理の開始ボタン
  button1 = (Button)findViewById(R.id.button1);
  button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      // スレッドの生成
      Thread thread =new Thread() {
        public void run() {
          changeText1("change text by post().");
        }
      };
      thread.start();
    }
  });
  
  // sendMessage()→handleMessage()を使用する処理の開始ボタン
  button2 = (Button)findViewById(R.id.button2);
  button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      // スレッドの生成
      Thread thread = new Thread() {
        public void run() {
          // sendMessage()→handleMessage()でUIを操作する。
          handler.sendEmptyMessage(100);
          
//          //これでもいける。Messengerはプロセス間通信で使うもの?
//          Messenger messenger = new Messenger(handler);
//          Message message = new Message();
//          message.what = 200;
//          try {
//            messenger.send(message);
//          } catch (RemoteException e) {
//            // TODO 自動生成された catch ブロック
//            e.printStackTrace();
//          }
        }
      };
      thread.start();
    }
  });
}

/**
 * {@link Handler#post(Runnable)})でUIを操作する。
 * TextViewに値をセットする。
 * 
 * @param text TextViewにセットする値
 */
private void changeText1(final String text) {
  handler.post(new Runnable() {
    @Override
    public void run() {
      textView1.setText(text);
    }
  });
}

参考ページ:
1.HandlerとMessage - 別スレッドでのGUI操作 - 愚鈍人
2.GPソフト Wiki - AndroidのHandlerとLooper
3.Handlerクラスの正しい使い方(Androidでスレッド間通信) - ちくたく
4.throw Life - AndroidのHandlerとは何か?

Androidアプリ開発メモ050:サービス その6:サービスのプロセス、スレッド

サービスについての以前の記事:
Androidアプリ開発メモ021:サービス
Androidアプリ開発メモ030:サービス その2
Androidアプリ開発メモ031:サービス その3:IntentService
Androidアプリ開発メモ032:サービス その4:バインドされたサービス
Androidアプリ開発メモ033:サービス その5:Messengerを使用したバインドされたサービス

サービスはデフォルトではそのサービスを開始したアクティビティと同じプロセス、スレッドで、つまりメインスレッドで実行される。
別スレッドだと思っていた^^;
※メインスレッド=アプリケーションが起動されたときにそのアプリケーション用に最初に作られるスレッド。UIを持つアプリケーションであればUIスレッドとも呼ぶ。

サービスをアプリケーションとは別プロセスで実行したい場合はAndroidManifest.xmlのservice要素にandroid:process属性を追加する。

android:process="<プロセス名>"
プロセス名が「:」(セミコロン)で始まる場合は「アプリケーションでプライベート」で、小文字で始まる場合は「グローバルプロセス」ということだが、その意味するところはよくわからないorz

参考ページ:
2. サービス - ソフトウェア技術ドキュメントを勝手に翻訳
Android Service - MyMemoWiki#p3
5. プロセスとスレッド - ソフトウェア技術ドキュメントを勝手に翻訳
サービスをアプリケーションプロセスから分離する - Kazzzの日記

Android SDK tools r16 のアップデートでトラブル

Android SDKのアップデートをしばらくしてなかったので確認したら Android SDK tools のr16が出ていたのでアップデートをかけた。
しかし、途中で

「A folder failed to be moved. On Windows this typically means that a program is using that folder (for example Windows Explorer or your anti-virus software.)…」

みたいな警告が出てきた。
指示に従ってウイルスバスターを切ってアップデートしなおしてみたがまた同じ警告が出た。
r15の時も同じ状況になって、その時はAndroid SDKをアンインストールしてからインストールしなおすという後ろ向きな方法で解決したw
しかしまたインストールしなおすのも嫌なのでググってみたら解決策が書いてある下記のページを見つけ、そこに書いてある方法でアップデートできた。

どうやら問題の原因は、SDKのアップデートにおいてSDKのインストール先フォルダをリネームをしようとするが、SDK Managerがそのフォルダにあるために自身がそのフォルダをロックしていてリネームできない、ということらしい。
間抜けだ。
これって必ず起きる問題なのでは?環境によっては問題なくアップデートできる場合もあるのか?
#Linux上やMac上の場合はよくわからないが。

以前、SDKのパスにスペースが入っている(たとえばデフォルトのインストール先である"C:\Program Files\android\android-sdk")場合にSDK Managerが起動しないってアホくさい問題があったが、今回の問題もなんかずいぶん低レベルだよなあ。
こんな入り口で躓くような問題はちゃんとつぶしてからリリースして欲しいよ。

参考ページ:[Android] Android SDKのAndroid SDK Toolsアップデート時に"A folder failed to be moved." エラーが発生する

January 08, 2012

#FF11 2012年1月第1週の活動状況

乱獲でシーフと忍者がカンストした。
忍者を主力にとしたいところだが、装備はそろっていないし片手刀・忍術のスキルも全然低い。スキル上げかあ。面倒だ^^;
LV上げ乱獲で伊賀襦袢が手に入らないかなーと思っていたが、伊賀襦袢はブンカールの金箱だったか。ミザレオの乱獲に参加してもそりゃ出ないわw

シーフソロでアビセアNMをやっている。
アエド足型紙目当てでブンカールのオポオポNMのHanumanとウサギNMのGnawtooth Garyをやっていた。
オポオポはタントラとランサーばかりで、ウサギはゴエティアがやたらと出て、肝心のアエドがなかなか出ない。
Hanumanは10回はやったと思うが2枚しか出なかった。ライバルが結構いて対戦すらできないことも結構あった。
8枚集まったが思ったより時間がかかった。
他にアートマ狙いで他のNMもやっている。ミザレオのコリブリNMで奇鳥のアートマをゲットした。

HNMはトリガ提供者総取りの募集に1回参加。
自分はソベクのトリガを使ったが、新たに6個集まった五行アイテムはない。
残るHNMのトリガはミザレオの三日月形の蒼色のジェイドだけだ。
乱獲に参加しないと五行集めは続かない。うーむ。
ソベク以外はキレイン、セドナ、ウルハドシ、クロリスをやった。
その時の主催者からの注意とか、メモ。
ソベク(ミザレオ)
・バブリザラ、耐寒カロル、シェルラを切らさない。
・ガとジャはスタン、ヘッドバッドで止める。
キレイン(ミザレオ)
・魅了技(メイヘムランターン)はスタン、ヘッドバッドで止める。
セドナ(ブンカール)
・特殊技を多く使うので弱点を突きにくい。
・バウォタラ、耐波カロル、シェルラを切らさない。
ウルハドシ(アットワ)
・吸収とかうざいので忍だけで削った。
クロリス(タロンギ)
・範囲死の宣告があるので聖水用意。後衛は魔法が届く範囲ギリギリにいること。でも死の宣告を食らった。

あと昨日、LSメンバーに手伝ってもらってデュナミス-サンドリアのボスを倒した。
できることならデュナミス-バストゥーク、デュナミス-ジュノもクリアして、北方の裏に行けるようになりたい。
そうすればLSメンバーがデュナミス-ボスディンだかザルカバードだかに一緒に行けるようになるのだが。
でも野良で「裏バス・ジュノ、クリア目的」って募集しても人が集まらないよなあ。

今後の活動。
・ブンカール乱獲の募集があれば伊賀襦袢狙いで参加。
・ジェイドとアートマ狙いでアビセア禁断・死闘エリアのNMをソロで刈る。
・胴と手の型紙集め。シーフ胴は@1なのでがんばってクエをやる。赤忍胴とシ忍手は自分で募集してNMやろうかな。
・機会があれば裏バスと裏ジュノ。ないだろうけど。

WMPでアルバムを統合する

1枚のアルバムからMP3ファイルを作ったのにWindows Media Playerのライブラリ>アルバムで表示すると複数のアルバムに分かれてしまう場合がある。同じアルバムが並んで表示され、収録曲がそれぞれに分かれて入っている。
曲順とかアーティスト名とかわかりやすい基準で分かれている訳ではない。WMPが何を見て別のアルバムと認識しているのかさっぱりわからん。

ID3タグのアルバム名を確認したがどの曲も同じアルバム名になっている。とりあえずID3タグエディタでアルバム名を付け直したりしてみたが状況は変わらず。
ググっても役に立ちそうな情報はなかった。

が、解決策は意外と簡単だった。
単純にドラッグ&ドロップしたらアルバムを統合できた。
たとえば2つのアルバムに分割されていたら、一方を他方にドラッグ&ドロップする。すると「アルバム名を書き換えて統合するけどOK?」みたいなダイアログが出るのでOKを押せばそれで統合できる。

WMPが何を基準にしてアルバムを分割していたのかは結局わからないままだが、とりあえず1枚のアルバムに統合できた。

January 01, 2012

PHPメモ004:演算子

比較演算子

==、!=、<>は値のみを比較する。
===、!==は値と型の両方を比較する。

論理演算子

論理積と論理和にはそれぞれANDと&&、ORと||があるが、優先度が違う。
&&と||は3項演算子、代入演算子より優先度が上。
ANDとORは3項演算子、代入演算子より優先度が下。
XORも3項演算子、代入演算子より優先度が下。

コード

$a = 1;
$b = "1";
echo '$a=' . $a . ' $b=' . $b . "<br />\n";

if ($a == $b) {
	echo "\$aと\$bは==で一致しました。<br />\n";
} else {
	echo "\$aと\$bは==で一致しましせんでした。<br />\n";
}
if ($a === $b) {
	echo "\$aと\$bは===で一致しました。<br />\n";
} else {
	echo "\$aと\$bは===で一致しましせんでした。<br />\n";
}

echo 'true &&  false ? "a" : "b" = ' . (true &&  false ? "a" : "b");
echo "<br />\n";
echo 'true and false ? "a" : "b" = ' . (true and false ? "a" : "b");
echo "<br />\n";

出力
$a=1 $b=1<br />
$aと$bは==で一致しました。<br />
$aと$bは===で一致しましせんでした。<br />
true &&  false ? "a" : "b" = b<br />
true and false ? "a" : "b" = 1<br />

実行演算子

バッククォートの中身をシェルコマンドとして実行し、出力を返す。

コード

$value = `dir /b`;
mb_convert_variables("UTF-8", "SJIS", $value);	// Shift-JISからUTF-8に変換して同じ変数に入れなおす

echo "<pre>${value}</pre>";

出力
<pre>analogClock.php
arrayInLiteral.php
average1.php
boolean.php
classExample.php
cmdSample.php
const01.php
elseifCondition.php
foreachLoop.php
hereDocument.php
ronri.php
strings.php
variable01.php
</pre>

エラー制御演算子

@はPHP式の前に付けた場合、その式により生成されたエラーメッセージは出力されない。
画面に何も出さない場合や独自のエラーメッセージを出したい場合に使用される。
たとえば、下記のように記述した場合に指定したファイルが存在しなくてもエラーメッセージは出力されない。

$fh = @fopen('non_exist_file.txt', 'r');

PHPメモ003:データ型

弱い動的型付け

PHPは弱い動的型付けの言語なので、変数がどの型になるかは実行時に動的に決まる。

文字列

引用符で囲まれた文字列では変数は展開されずエスケープシーケンスは無効である。
二重引用歩で囲まれた文字列では変数は展開されエスケープシーケンスは有効である。ただし変数は波括弧で囲む。

ヒアドキュメント

改行を含む長い文字列を表現するのに便利。IDは"ID"じゃなくても分かりやすいものを付けられる。たとえば長いSQL文ならIDは"SQL"とか。
文字列内に変数があれば展開される。

<<<ID
<任意の文字列>
ID
コード
$name = '山田太郎';

$str1 = '氏名:${name}<br />\n';
$str2 = "氏名:${name}<br />\n";
$str3 = "氏名:{$name}<br />\n";

$str4 = <<<SQL
SELECT
  s.ProductID, p.ProductName, SUM(s.Quantity) AS total
FROM
  Sales AS s 
  JOIN Products As p 
  ON s.ProductID = p.ProductID
GROUP BY
  s.ProductID, p.ProductName
ORDER BY
  s.ProductID
SQL;

$str5 = <<<MESSAGE
ユーザ${name}はアクセス権がありません。<br />
アクセス権を持つユーザでログインしてください。<br />
MESSAGE;
?>

<?= $str1 ?>
<?= $str2 ?>
<?= $str3 ?>

<pre>
<?= $str4 ?>
</pre>

<?= $str5 ?>

出力
氏名:${name}<br />\n氏名:山田太郎<br />
氏名:山田太郎<br />

<pre>
SELECT
  s.ProductID, p.ProductName, SUM(s.Quantity) AS total
FROM
  Sales AS s 
  JOIN Products As p 
  ON s.ProductID = p.ProductID
GROUP BY
  s.ProductID, p.ProductName
ORDER BY
  s.ProductID</pre>

ユーザ山田太郎はアクセス権がありません。<br />
アクセス権を持つユーザでログインしてください。<br />

論理型

TRUEとFALSEの2値のみ。大文字小文字は区別しない。
論理型が文字列に自動変換される場合、
TRUE → "1"
FALSE → 空文字列
となる。
論理型への変換においては、FALSEとみなされるのは以下である。

  • 整数の0
  • 浮動小数点数の0.0
  • 空文字列
  • 文字列の"0"
  • NULL
  • 初期化されていない変数の値
  • 要素数0の配列

コード

$bool1 = TRUE;
$bool2 = FALSE;
echo "TRUEは文字列に変換すると\"${bool1}\"<br />\n";
echo "FALSEは文字列に変換すると\"${bool2}\"<br />\n";

$a = 0;
if ($a)	echo "0はTRUEとみなされる。<br />\n";
else	echo "0はFALSEとみなされる。<br />\n";

$b = "";
if ($b)	echo "空文字列はTRUEとみなされる。<br />\n";
else	echo "空文字列はFALSEとみなされる。<br />\n";

$c = "0";
if ($c)	echo "文字列\"0\"はTRUEとみなされる。<br />\n";
else	echo "文字列\"0\"はFALSEとみなされる。<br />\n";

if ($d)	echo "初期化されていない変数はTRUEとみなされる。<br />\n";
else	echo "初期化されていない変数はFALSEとみなされる。<br />\n";

$e = array();
if ($e)	echo "要素数0の配列はTRUEとみなされる。<br />\n";
else	echo "要素数0の配列はFALSEとみなされる。<br />\n";

$f = 1;
if ($f)	echo "1はTRUEとみなされる。<br />\n";
else	echo "1はFALSEとみなされる。<br />\n";

$g = "a";
if ($g)	echo "\"a\"はTRUEとみなされる。<br />\n";
else	echo "\"a\"はFALSEとみなされる。<br />\n";

出力
TRUEは文字列に変換すると"1"<br />
FALSEは文字列に変換すると""<br />
0はFALSEとみなされる。<br />
空文字列はFALSEとみなされる。<br />
文字列"0"はFALSEとみなされる。<br />
初期化されていない変数はFALSEとみなされる。<br />
要素数0の配列はFALSEとみなされる。<br />
1はTRUEとみなされる。<br />
"a"はTRUEとみなされる。<br />

MySQLメモ001:コマンドラインクライアント

環境はMySQL 5.5.19、Windows 7 Home Premium (32bit)。

コマンドラインクライアントの場所:
<MySQLのインストールフォルダ>\MySQL Server 5.5\bin\mysql.exe

クライアントの起動
mysql -u <ユーザ名> -p

サーバ情報の表示
STATUS

サーバの詳細情報の表示
SHOW GLOBAL STATUS

DBを作成
CREATE DATABASE <データベース名>

DB一覧を表示
SHOW DATABASES

DBに接続
USE <データベース名>

テーブル一覧を表示
SHOW TABLES

テーブルの詳細情報を表形式で表示
SHOW TABLE STATUS FROM <データベース名>

テーブルの詳細を表示
DESC <テーブル名>
SHOW COLUMNS FROM <テーブル名>

ユーザの登録と権限の付与
GRANT ALL PRIVILEGES ON {<テーブル名>|*|<データベース名>.*} TO <ユーザ名> IDENTIFIED BY '<パスワード>';

コマンドが記述されたファイルを読み込んで実行
SOURCE ファイル名

終了
QUIT

実行例
C:\applications\MySQL\MySQL Server 5.5\bin>mysql -u javauser -p
Enter password: *********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.5.19 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.5.19, for Win32 (x86)

Connection id:          7
Current database:
Current user:           javauser@localhost
SSL:                    Not in use
Using delimiter:        ;
Server version:         5.5.19 MySQL Community Server (GPL)
Protocol version:       10
Connection:             localhost via TCP/IP
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3306
Uptime:                 1 hour 12 min 11 sec

Threads: 1  Questions: 32  Slow queries: 0  Opens: 36  Flush tables: 1  Open tab
les: 3  Queries per second avg: 0.007
--------------

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| java_sample_db     |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql> use java_sample_db
Database changed
mysql> show tables;
+--------------------------+
| Tables_in_java_sample_db |
+--------------------------+
| account                  |
| wiki_page                |
+--------------------------+
2 rows in set (0.08 sec)

mysql> show table status from java_sample_db;
+-----------+--------+---------+------------+------+----------------+-----------
--+-----------------+--------------+-----------+----------------+---------------
------+-------------+------------+-----------------+----------+----------------+
---------+
| Name      | Engine | Version | Row_format | Rows | Avg_row_length | Data_lengt
h | Max_data_length | Index_length | Data_free | Auto_increment | Create_time
      | Update_time | Check_time | Collation       | Checksum | Create_options |
 Comment |
+-----------+--------+---------+------------+------+----------------+-----------
--+-----------------+--------------+-----------+----------------+---------------
------+-------------+------------+-----------------+----------+----------------+
---------+
| account   | InnoDB |      10 | Compact    |    4 |           4096 |       1638
4 |               0 |            0 |  10485760 |           NULL | 2012-02-16 20:
07:42 | NULL        | NULL       | utf8_general_ci |     NULL |                |
         |
| wiki_page | InnoDB |      10 | Compact    |    1 |          16384 |       1638
4 |               0 |            0 |  10485760 |           NULL | 2012-02-27 14:
08:12 | NULL        | NULL       | utf8_general_ci |     NULL |                |
         |
+-----------+--------+---------+------------+------+----------------+-----------
--+-----------------+--------------+-----------+----------------+---------------
------+-------------+------------+-----------------+----------+----------------+
---------+
2 rows in set (0.05 sec)

mysql> source c:/data/sql.txt
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+
4 rows in set (0.00 sec)

mysql> quit
Bye

C:\applications\MySQL\MySQL Server 5.5\bin>

参考ページ:MySQLクイック・リファレンス

2012

紅白歌合戦は水城奈々だけ見ようと思っていたが、FF11やってて気づいたら終わっていたw
それからDVDでアニメを見ていたら年が明けていたww
ダメダメだな。

去年は未曾有の大災害が東北を襲った。
今年は大きな地震がないといいなと思ったが、もしかしたらそれは単なる「先送り」なのかもしれない。
東海地震・東南海地震・南海地震はいずれ、そう遠くないうちに起きるのだから。

年末にユーロ円が100円を割った。ユーロ危機はどうなるのか。
「辰巳天井」って言うし、株式アナリストは楽観的な人が多いけど、「年末には日経平均1万1千円台」なんて信じられません。

マヤ暦の終わりで人類滅亡だっけ?
まあ、この世の終わりまできちんと生きましょう。
とりあえず今日は徒歩30秒のところにある神社に初詣に行って、なるべく自然災害が少ない年になることを祈ってこよう。

« December 2011 | Main | February 2012 »

March 2017
Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
無料ブログはココログ

日本blog村

  • にほんブログ村 IT技術ブログへ
  • にほんブログ村 アニメブログへ
  • にほんブログ村 サッカーブログ アルビレックス新潟へ

好きな音楽家

メモ

XI-Prof