Android Make Days in 明星和楽 にスタッフとして参加してきました
11/11金 - 12土 で行われた Android Make Days in 明星和楽。
今回自分はスタッフとして参加させていただきました。
メイン作業は司会。
部屋が複数あるので3人で交代しつつ、とのことだけども。
こんなでかいイベントで司会とか!!不安でガクブル。
と、自分のことはさておき、まずはスタッフ視点を含めつつレポート書いてみようかと。
各セッションについての素晴らしいエントリはもういくつもあるし。
というわけで早速。
(写真多めですー)
11/11(金)
24Makeコンテスト。
場所は GuildCafe Costa。
金曜夜から24時間でアプリ作って土曜に発表、というクレイジーなイベントw
仕事終わって皆様の頑張る様子をチラ見しにきてみた。
来年は作る側で参加しようかなー。すごく楽しそうだった。
参加者の皆様の様子。
11/12(土)
9:00
スタッフメンバー集合。
場所は 福岡県Rubyコンテンツ産業振興センター。
自分は間違えて金曜の会場、GuildCafe Costa へ行ってしまうという醜態をさらすw
会場設営やったり。
スタッフミーティングやったり。
11:00
ホモ弁に予約していたスタッフメンバー分の弁当を受け取り行ったり。
司会させていただくセッションの講師の皆様と打ち合わせしたり。
弁当食べながら司会メンバーで打ち合わせの図。
twicca作者の @R246氏(青山さん) とパシャリ。
あんざいゆきさん との打ち合わせ。
自分はあんざいさんの大ファンなのでサインいただいちゃいました。
うん、自分きもいですねw
イベント開始前にみんなで交代で弁当タイム。
鹿。どや。
世界の みよしさん 発見!
13:00
開場。
参加者が続々。
すぐにメイン会場が埋まる。
受付の様子
美女ぞろい。
ステッカーたくさん。
オープニング、基調講演。
ブースの様子。
Arduino体験講座。
レッドブル様との交流w
LT会場。大盛況。
個人的にどストライクだったのが、
ブリリアントサービス様のNFCクエスト体験。
@R246氏、サイバーエージェント三島木さん と超強力なパーティ組んで挑んだものの。。
敗北('A`)
魔王強い。
ブースの皆様と。
19:00
閉会式。
全員で手を繋いでスタッフ一同挨拶。
19:30 - 21:00
懇親会。
乾杯。
わいわい。
三島木さんとあんざいさん
後片付け後、残っていたメンバーで集合写真。
終了後。
スタッフ数名で一緒に明星和楽Gates会場へ行ったあと、途中離脱して屋台へ移動。
屋台の後は酔っぱらってひとりで中洲をうろうろして川沿いで寝てた。(ひどい)
で、結局タクシーで5時すぎに帰宅。
イベントを終えて。
正直なところ、スタッフメンバーはイベント屋ではないので普段の自分の業務もある。
そんな状況下でも各メンバーが責任もってタスクをちゃんとこなし、
結果、イベントは大成功っていうのはやっぱりすごいことじゃないかと。
イベント終了後になんだかイロイロと考えてしまった。
いやー!!!本当に楽しかった!!
スタッフとして参加できて本当によかった!!
次回もぜひスタッフとして参加したいし、何かを発信する側にもなりたい。
改善すべき、反省すべき点はもちろんたくさんあるけれども、
イベント運営の難しさと楽しさを味わうことができて、
すごく貴重ないい経験ができた、参加できてよかった、楽しかった、というのが本音。
運営スタッフの皆様、講演者の皆様、参加された皆様、
本当にお疲れさまでした!!
Intentの作り方
Activity/Service起動用のIntentを作るとき、
皆どうやってるのだろう、とふと疑問。
例えば Activity#onCreate 内で
「Service(test.intent.TestService)起動用のIntent」 を作るとする。
基本的な作り方はこんなかんじになるのかな?
@Override public void onCreate(Bundle savedInstanceState) { 〜 // コンストラクタのみ で作る場合 Intent intent1 = new Intent(this, TestService.class); Intent intent2 = new Intent(getApplicationContext(), TestService.class); // コンストラクタ(引数なし)+setClassName で作る場合 String packageName = getPackageName(); String className = TestService.class.getCanonicalName(); Intent intent3 = new Intent(); intent3.setClassName(packageName, className); }
自分の場合は intent1、2 みたいにコンストラクタ1行で済ませることが多い。
web上のサンプル見てもこのパターンが多い気がする。
通常はこれでいいはず。楽だし。
ここで出た疑問。
ApplicationContext を渡す必要があるのだろうか。
Intent のソースを確認してみたところ、
本来は ApplicationContext を引数に渡す必要などなく、
最低限必要なのはこれ↓↓だけだった。
Intent作成に必要な情報
- アプリケーションのパッケージ名
- 起動するクラス名
1は AndroidManifest.xml の
起動するクラス(TestService)のパッケージ名ではない。
2は 起動するActivity/Service等のクラス名(パッケージ名まで含む)。
引数に渡された ApplicationContext は、内部で
「アプリケーションのパッケージ名」 を取得するために使ってるだけ。
まーつまり intent1、2、3 はどれも同じなので、
作りたい作り方でおk、ということでしたw
Intent.java(抜粋)
public Intent() { } public Intent(Context packageContext, Class<?> cls) { mComponent = new ComponentName(packageContext, cls); } public Intent setClassName(Context packageContext, String className) { mComponent = new ComponentName(packageContext, className); return this; }
ComponentName.java(抜粋)
public ComponentName(String pkg, String cls) { if (pkg == null) throw new NullPointerException("package name is null"); if (cls == null) throw new NullPointerException("class name is null"); mPackage = pkg; mClass = cls; } public ComponentName(Context pkg, String cls) { if (cls == null) throw new NullPointerException("class name is null"); mPackage = pkg.getPackageName(); mClass = cls; } public ComponentName(Context pkg, Class<?> cls) { mPackage = pkg.getPackageName(); mClass = cls.getName(); }
話変わって。
intentって文字列定義みたいなもんだから、
できれば 「static final」 定義で、static初期化子 内で作っておきたいなー、
なんて自分は思ってたりする。後から編集しないようなintentは特に。
でも 「アプリケーションのパッケージ名」 は
static初期化子 内で動的に取得できない。
ということは、こんなかんじで固定値定義するしかないのか??
private static final Intent intent; static { String packageName = "test.intent"; String className = TestService.class.getCanonicalName(); intent = new Intent(); intent.setClassName(packageName, className); }
うーん。微妙。
別スレッドでキュー管理(Handler, Looper, HandlerThread)
非同期処理を組んでると、
「別スレッド上でも Handler みたいなキュー管理がしたい」
って時があったりしますよねー。(きっと)
そんなとき、HandlerThread を使うとわりと簡単に実装できたりする。
HandlerThread は java.lang.Thread を継承したクラスで、
android標準の Handler と組み合わせて使うための仕組みが入ってたり。
具体的な使い方。
まずは Handler(defaultコンストラクタ) を使う場合。
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }); }
実行すると当然 「main」 と出力される。
当然、mainスレ上でキューが実行される。
これは問題ないですね。
次に Handler+HandlerThread の場合。
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 別スレ生成 -> 開始 HandlerThread handlerThread = new HandlerThread("other"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); handler.post(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }); }
実行すると 「other」 と出力される。
キューが実行されてるスレッドが mainスレ から 別スレ に変更されます。
もちろんこの Handlerインスタンス は別スレ上で使用してOK。
手順をまとめるとこんなかんじ。
- 別スレッド(HandlerThread)を生成
- 別スレ開始
- HandlerThreadインスタンス から Looperインスタンス 取得
- Handlerインスタンスを生成(3で取得した Looperインスタンス を 引数指定)
- 4 で作成した Handlerインスタンス を使用(Handler#post 等)
今まで PriorityBlockingQueue とか使って、
自前のキュー管理クラス作ってた自分涙目。
キューをFIFOで実行するだけのキュー管理であれば、
このやり方でまったく問題なさそうですね。
framework ではどうやってるのかなーと思い、
Looper、Handler、HandlerThread のソースを読んでみた。
ポイントはこのあたり。
- コンストラクタ Handler(default) は「mainスレッド上で作成された」 Looperインスタンス を使用
- コンストラクタ Handler(Looper) は「引数で渡された」 Looperインスタンス を使用
- Looperインスタンスは Looper#prepare を呼び出すと生成される(ThreadLocal保持)
- HandlerThread は Thread を継承したクラス
- HandlerThread#run の中で Looper#prepare を呼び出している
Looperインスタンスの生成場所 の違い。
なるほど。
東日本大震災から半年経って思うこと
実は母親と祖父が福島に住んでいたりする。
原発から半径数十キロとかそのレベル。
直接的な津波の被害にはあっていないのだが、
震災が起きた際にはもちろん電話も通じず、物流も止まってた。
ただ、わりと早い時間で電気/ガスも復旧し、
今は普段どおりの生活はおくれているみたい。
震災直後。
電車も不通、道路もどうなっているかわからない。
祖父の家までたどりつけるかもわからない。
けど、このままだとどうなるかわからないから直接迎えに行く、
と言ったが、親からは絶対に来るな、と言われた。
私らは寿命まであと20数年。あんたは今からまだ長い。
今から結婚して子供生んだり育てたりするだろう。
原発の状況がわからない、どうなるかわからない場所には
絶対に来るな、来るのは親不孝な行為だ、と。
まーそんなこと言われても子の立場としては心配で仕方ない。
でもどうにもできず、ヤキモキしながら今を過ごしている。
ついこの間。
何かを見てて考えさせられることがあった。
両親とはあとどれくらい会えるのだろう、話せるのだろう、と。
両親は二人とも去年還暦を迎えて。
考えたくないけど、平均寿命とかイロイロ考えるとあと25年くらいなのか?
自分の場合、実際のところ年間何日会っているだろう。
月1回会うとしても年間12回。
12日×25=300日。
この数字を見て考えてしまった。
1年もないのか、と。
会える時間をもっと大事にしないといかんなー、と。
いろんなことを後悔しないように、と。
東日本大震災から半年。
メディアからは震災関連情報がだいぶ減ってきた。
震災直後ほど頭の中がそのことでいっぱいではない自分もいる。
若干麻痺してきているというか慣れつつあるというか。
でもやっぱり、自分の身内が被災しているので余計に他人ごととは思えない。
復興に関してもし自分にできることがあれば、
これからも少しでも協力できたらいいなと考えている。
ありがたいことに、@kuneen 作曲の被災地復興応援ソングプロジェクトの
バックコーラスに参加させていただきました。
元気が出るとてもいい曲なので、
たくさんの方に聴いていただけたら、と思ってます。
震災で亡くなった方々のご冥福を心よりお祈りいたします。
Error generating final archive(Debug Certificate expired on~) が発生する
androidプロジェクト をビルド時に突然こんなエラーが出るようになった。
Error generating final archive: Debug Certificate expired on 〜
調べてみると「デバッグ用証明書の期限切れ」で発生するエラー、とのこと。
対処方法は2種類あるみたい。
- debug.keystoreファイルを再生成する
- 有効期限を長くする
というわけで具体的な手順。
1.debug.keystoreファイルを 削除->再生成 する
手順
debug.keystoreファイルパスはココを見ればおk。
eclipseの「Preferences - Android - Build」の「Default debug keystore」
2.有効期限を長くする
こちらを参考にさせていただきました。
Androidの「Debug certificate expired」エラーの対処方法
毎年やることになるけど、今回は 1 を採用。
debug.keystoreのデフォルト有効期限は1年。
ということは、この1年、特にOS再インストールとかやってないので、
Android開発初めてちょうど1年が経過した、ということになるのか??
これはなんだか感慨深い!!
というわけでちょっと振り返ってみた。
この1年で公開したアプリはーー
- 定点カメラアプリ(無音で定期的にタイマ撮影)
- カメラプレビュー画面で顔認識して顔の上にう○こ載せるアプリ
うーむ。。
ろくなアプリがない。。
AndroidMarketにも似たようなアプリ多数。
個性がないw