2011年6月28日火曜日

androidのbuildが32bitでも出来るようになってた?


androidのソースの中身が更新されていて64bitじゃなきゃビルド無理ーな部分が消えていた。
実際、何も変更加えなくてもbuildできた。
でも、HPには8GBのRAMが必要って書いてあったけど、virtual machineじゃないからOK??
良く解らん。


マシンのスペックを晒すと以下のような感じ。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.04
DISTRIB_CODENAME=lucid
DISTRIB_DESCRIPTION="Ubuntu 10.04.2 LTS"


$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz
stepping : 10
cpu MHz : 2003.000
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm tpr_shadow vnmi flexpriority
bogomips : 5652.55
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz
stepping : 10
cpu MHz : 2003.000
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
apicid : 1
initial apicid : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm tpr_shadow vnmi flexpriority
bogomips : 5652.46
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 2
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz
stepping : 10
cpu MHz : 2003.000
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 2
cpu cores : 4
apicid : 2
initial apicid : 2
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm tpr_shadow vnmi flexpriority
bogomips : 5722.90
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz
stepping : 10
cpu MHz : 2003.000
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 3
cpu cores : 4
apicid : 3
initial apicid : 3
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm tpr_shadow vnmi flexpriority
bogomips : 5652.50
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:


$ cat /proc/meminfo
MemTotal: 3355252 kB
MemFree: 842344 kB
Buffers: 196160 kB
Cached: 1619120 kB
SwapCached: 3308 kB
Active: 1101240 kB
Inactive: 1249040 kB
Active(anon): 221664 kB
Inactive(anon): 320800 kB
Active(file): 879576 kB
Inactive(file): 928240 kB
Unevictable: 0 kB
Mlocked: 0 kB
HighTotal: 2498184 kB
HighFree: 624792 kB
LowTotal: 857068 kB
LowFree: 217552 kB
SwapTotal: 9823708 kB
SwapFree: 9809132 kB
Dirty: 112 kB
Writeback: 0 kB
AnonPages: 532084 kB
Mapped: 44960 kB
Shmem: 7456 kB
Slab: 98232 kB
SReclaimable: 85304 kB
SUnreclaim: 12928 kB
KernelStack: 2616 kB
PageTables: 6432 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 11501332 kB
Committed_AS: 1298504 kB
VmallocTotal: 122880 kB
VmallocUsed: 70356 kB
VmallocChunk: 34300 kB
HardwareCorrupted: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 4096 kB
DirectMap4k: 36856 kB
DirectMap4M: 872448 kB


全然関係ないけど、bloggerにも「+1」ボタンが増えていますね。

2011年6月15日水曜日

TYPE_SYSTEM_ALERTでいつでも一番上


なんか震災から落ち着かない日々が続いていたので、
全然かけてなかったけど書くかな。

Dock4DroidとかWave Launcherなど、Androidにおいて、
すべての画面で例外なく一番上にUI部品を配置する方法についてメモを取っておく。

基本的には
http://harehare1110.blogspot.com/2011/04/android-view.html
を参照すればそのようなことができる。
でもTYPE_SYSTEM_OVERLAYを使うとキーイベントとかが全部捨てられてしまうので、
TYPE_SYSTEM_ALERTを使う。
http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html
にWindowManager.LayoutParamsの説明がある。

public static final int FLAG_LAYOUT_NO_LIMITS
Since: API Level 1
Window flag: allow window to extend outside of the screen.

とか試してないけど、面白そうなフラグもあった。

で、自分でも試したいので、サンプルを作った。以下に置いてある。
https://github.com/matsuhiro/TestForTYPE_SYSTEM_OVERLAY
気をつけるのは、
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
をManifestに書くくらいで、作ったソースのフラグとかは以下のよううな感じ。
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
    WindowManager.LayoutParams.FLAG_FULLSCREEN |
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
    PixelFormat.TRANSLUCENT);
  WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
FLAG_NOT_FOCUSABLEを入れてあげないと裏側の画面がうまく動かない。。。
でもAndroidってフォーカスが当たっているところにイベント配信する仕組みだったような??
InputMethodもViewキッカケだと起動しないみたいだし。
なんでもかんでも好きなようには出来ないかもですね(^^ゞ


調べてみて思ったのは、Dock4DroidとかWave Launcherなどのランチャーなら
こういった仕組みは便利だけど、それ以外だとちょっと使い道がなさそうということ。
今ランチャー以外で考えつくのは、C2DMとかのキッカケで全画面に
このようなViewを貼りつけて強制的に端末を操作不能にするとか?
うーむ。なんか危ないなこの仕組。
面白いけど、端末ベンダーの証明書で署名されていないアプリは
使えないようにしたほうがいいじゃねぇかな。

2011年4月11日月曜日

続:Fragmentとandroid-support-v4.jar




気になったので、シーケンスとか描いてみた。

2.3.3 & android-support-v4.jarのシーケンス

3.0のシーケンス

android-support-v4のソースの中身を見てみたが、
どうやら
FragmentActivity内のonPostCreateで、
dispatchActivityCreatedしているのが問題の模様。
http://developer.android.com/guide/topics/fundamentals/fragments.html
には、ActivityのonStartと同じタイミングで
FragmentのonActivityCreatedのあとでのonStartがコールされるはずであり、
これに関しては問題ない模様であるが、
onStart後にコールされるonPostCreatedのタイミングで
またActivityCreatedしようとしてしまっている。
なので、FragmentActivity#onPostCreate内のdispatchActivityCreatedをコメントアウトすれば治りそうな予感。

まあ、それでもActivityの呼び出し元からFragmentのmethodを呼び出すのではなく、
Activityを拡張したFragmentActivityからFragmentのmethodを呼び出しているわけだから
シーケンスのタイミングのずれが発生するのは仕方の無いことか。。。

2011年4月6日水曜日

Fragmentとandroid-support-v4.jar


"SDK"/extra/android/compatibilityにある
FragmentManager.javaを読んだけど
新しいUI部品というよりはユーティリティーの追加のように感じる。
本来のFragmentの実装ではなく
Fragmentとほぼ同じ機能を有した外部ライブラリとして
FragmentActivityとかを実装しているわけだから、それは仕方のないことかも。
サンプルとしては、
FramgnetStackSupport.javaを参考にすればいい。
基本的には、FragmentXXXSupport.javaが外部ライブラリを利用したサンプルになる。

だが、そもそもFragmentを利用するメリットはどこにあるのだろうか?
画面遷移が画面全体の一部の差し替えになることで
かっこいいUIをつくることが出来る。
これは、Viewのadd removeでも出来たことだ。
でも、なんであえてこんなモノがあるのかの理由は
http://android-developers.blogspot.com/2011/02/android-30-fragments-api.html
に書いてある。
XMLを変えて、Activityを一部増やすことで
tablet向けにつくっていたActivityをソースコードをまるまる流用して
二つのActivityに分けることが出来ると言っているわけだ。

ただ、ここで気になってくるのがライフサイクルだ。
compatibilityの外部ライブラリを利用した場合の
FragmentとActivityのライフサイクルと
本来のFragmentとActivityのライフサイクルが一緒なのだろうか?
結論を書くと全然違った!!

ApiDemosにあるFragmentHideShow.javaをほとんどパクって
compatibilityの外部ライブラリを利用して作成したプロジェクトと
3.0の本物のFragmentを利用して作成したプロジェクトを作った。
長いからサンプルコードは貼り付けないが、
FragmentActivityはActivity
FirstFragmentはFragment
SecondFragmentはFragment
で、その各コールバックにEnter/Exitのログを仕込んだ。
Logcatで見えやすいのでログレベルをあえて分けた。

2.3.3 & android-support-v4.jarで作ったFragmentのサンプル


3.0で作ったFragmentのサンプル



結果としては、
2.3.3 & android-support-v4.jarのログ
----------------------------------------
Enter FragmentActivity#onCreate
Enter SecondFragment#onAttach
Exit SecondFragment#onAttach
Enter SecondFragment#onCreate
Exit SecondFragment#onCreate
Enter SecondFragment#onCreateView
Exit SecondFragment#onCreateView
Enter FirstFragment#newInstance
Exit FirstFragment#newInstance
Exit FragmentActivity#onCreate
Enter FragmentActivity#onStart
Enter FirstFragment#onAttach
Exit FirstFragment#onAttach
Enter FirstFragment#onCreate
Exit FirstFragment#onCreate
Enter SecondFragment#onActivityCreated
Exit SecondFragment#onActivityCreated
Enter SecondFragment#onStart
Exit SecondFragment#onStart
Enter FirstFragment#onCreateView
Exit FirstFragment#onCreateView
Enter FirstFragment#onActivityCreated
Exit FirstFragment#onActivityCreated
Enter FirstFragment#onStart
Exit FirstFragment#onStart
Exit FragmentActivity#onStart
Enter SecondFragment#onStop
Exit SecondFragment#onStop
Enter FirstFragment#onStop
Exit FirstFragment#onStop
Enter FragmentActivity#onResume
Exit FragmentActivity#onResume
Enter SecondFragment#onStart
Exit SecondFragment#onStart
Enter SecondFragment#onResume
Exit SecondFragment#onResume
Enter FirstFragment#onStart
Exit FirstFragment#onStart
Enter FirstFragment#onResume
Exit FirstFragment#onResume
----------------------------------------

3.0のログ
----------------------------------------
Enter FragmentActivity#onCreate
Enter SecondFragment#onAttach
Exit SecondFragment#onAttach
Enter SecondFragment#onCreate
Exit SecondFragment#onCreate
Enter SecondFragment#onCreateView
Exit SecondFragment#onCreateView
Enter FirstFragment#newInstance
Exit FirstFragment#newInstance
Exit FragmentActivity#onCreate
Enter FirstFragment#onAttach
Exit FirstFragment#onAttach
Enter FirstFragment#onCreate
Exit FirstFragment#onCreate
Enter FragmentActivity#onStart
Exit FragmentActivity#onStart
Enter SecondFragment#onActivityCreated
Exit SecondFragment#onActivityCreated
Enter SecondFragment#onStart
Exit SecondFragment#onStart
Enter FirstFragment#onCreateView
Exit FirstFragment#onCreateView
Enter FirstFragment#onActivityCreated
Exit FirstFragment#onActivityCreated
Enter FirstFragment#onStart
Exit FirstFragment#onStart
Enter FragmentActivity#onResume
Exit FragmentActivity#onResume
Enter SecondFragment#onResume
Exit SecondFragment#onResume
Enter FirstFragment#onResume
Exit FirstFragment#onResume
----------------------------------------

全然違う。。。
ぱっと見た感じだと
android-support-v4.jarを利用したほうがバグっているような。。。
3.0のソースを見ることが出来ないから、どんな理由でこのような差分が出ているのか
正確なところは解らない。
でも今のところFragmentを3.0以外で利用するのは控えたほうが無難かも。
少なくともそのまま流用は考えないほうがいいと思う。

2011年4月3日日曜日

Google Apps Scriptが使えそう



Google Apps Script(GAS)が気にはなっていたけど、
特に使いたいシーンもないし使っていなかった。
最近、東京電力が電力の利用状況をCSVで公開し始めた。
こいつを利用したアプリをマーケットに公開したが、
東京電力からのデータは一日分だけしか手に入らないし、
最新の情報であっても時間にすれば1時間半以上前の情報になってしまっている。
本当に知りたいのは、30分か1時間後の予測値だと思う。
それを実現するための第1歩として、データの収集がある。
収集しておいて、それを後で利用するためにサーバ立ててDBに入れて、
取り出すためのIF定義して。。。
みたいなことをしなければいけないほど大規模なデータでもない。
1日24要素なので、1年間続けたとしても9000弱の要素しかない。
なので、Google DocsのSpreadSheetに入れればいいし、GASで遊んでみたたいし。。。

GASを利用するためには
といった感じでスクリプトエディタを開いて、
のようなスクリプトを書く。Javascriptで。
初めてJavascript書いた。はずい。。。

そして、自動でデータを集めたいので定期実行するわけだが、
「トリガー」の中のメニューを選ぶと
のような画面になる。上の絵では10分おきにgetTodenDataを実行している。


自動で最新のデータがSpreadSheetに保存出来た。
データが欲しいときは、
ただ見たいなら
https://spreadsheets.google.com/ccc?key=0Arsm5M6qVMHDdEJDZUVTbTg5UWxWbGJ4Rm1ISVF1RHc&hl=en&output=html

CSVでデータが欲しいのであれば
https://spreadsheets.google.com/ccc?key=0Arsm5M6qVMHDdEJDZUVTbTg5UWxWbGJ4Rm1ISVF1RHc&hl=en&output=csv
とすることで誰でもダウンロードできる。


自分は普段スクリプト言語使わないし、
使ったことあるとしてもコピペーしかしたことが無かったけど、
一応、目的のものを作ることが出来た。
書いたのは画像で貼り付けた関数一つだけなので、
それで、定期実行やデータの公開が出来るのは非常に便利だと思う。

2011年3月29日火曜日

シリコンバレーカンファレンスに行って来た。


いまさらではあるが、
今月の初めにシリコンバレーカンファレンスに行って来た。
アメリカにいる最中に地震とかあって、なんだか落ち着かない旅であった。

シリコンバレーは、ソフトウェアとか色々生まれているところではあるが、
会社自体はドコも一緒だなぁ。というのが感想。
ダメなマネージャーはいるし、
開発プロセスがめちゃくちゃだったり、
給料は高そうであるが、出費も多くなるし、
田舎過ぎて経済的な効率はかなり悪そう。
住みやすい場所ではない。

そして、一番印象的だったのは、シリコンバレーにある会社でも
実装を東欧の賃金の安いとこで行っていたことだ。
全部の会社がそうであるわけではないし、
普通に考えれば当たり前だけど、シリコンバレーでも
賃金の安いところに実装(当然詳細設計もだろう)を出しているわけだ。
これを聞いて、ますますドコも一緒だと感じた。

ただ、シリコンバレーはたいしたことないとか思ったわけでもない。
GoogleもAppleもシリコンバレーにあるし、
ケータイのOS作りたかったら、シリコンバレーに行くしかない。

日本のソフトウェアの業界でもぜひシリコンバレーのようであって欲しい点としては、
人同士のつながりが、次の職場を決めていく感じとか
自分が何をしているのかカンファレンスとかに出て発表したりしていないと
職にありつけなさそうな所だ。
自分の能力を人に伝える努力をしないと職にあぶれるのはかなり厳しいけれど、
とても良いところだと思う。
こういった仕組みがあれば、
パワポ職人みたいなエンジニアもどきの数は、多少は減るだろうと思う。

ただ、東京でもモバイル端末のアプリケーションに関しては、
上のような仕組みがそのうち生まれ始めるのではないかと思っていたりする。

2011年2月27日日曜日

AndroidのLooper覚書


デ部に参加したときにLooperの話を聞いた。
なんとなくは解ったけど実際のところどうなのか微妙な理解なので
ソースをみてみた。
frameworks/base/core/java/android/os/Handler.java
の109行目あたりにコンストラクタがある(この辺のソースは、そうそう変わらないだろうから行数かいてみた)が、
prepareしていないとエラーが起こるような仕組みになっている。
なので、
new Thread(new Runnable() {
   @Override
   public void run() {
    Handler handler = new Handler();
    
   }
   
  }).start();
こんなことすると落ちる。
UI threadの場合はActivityが作成される際に、Looper.java内のprepareMainLooper()がコールされて、準備OKになるけど、UIでないthreadは自分でprepareしてあげないといけない。
そのことはLooperのjavadocコメントに書いてあったりする。
class LooperThread extends Thread {
 public Handler mHandler;
 public void run() {
  Looper.prepare();
  
  mHandler = new Handler() {
   public void handleMessage(Message msg) {
    // process incoming messages here
   }
  };
  
  Looper.loop();
 }
}
こんな感じで書いてみればーって感じでコメントがある。

でも、実際どーやって使うの?
って感じなので動くサンプルかいてみた。
package com.matsuhiro.android.loopersample01;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class LooperSample01 extends Activity {
 private static final String TAG = "LooperSample01";
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  Button btn_ui = (Button) findViewById(R.id.button1);
  Button btn_not_ui1 = (Button) findViewById(R.id.button2);
  Button btn_not_ui2 = (Button) findViewById(R.id.button3);

  Thread th = Thread.currentThread();
  long id = th.getId();
  Log.v(TAG, "onCreate ui id="+id);
  
  final LooperThread lt = new LooperThread();
  lt.start();
  
  btn_ui.setOnClickListener(new View.OnClickListener() {
   
   @Override
   public void onClick(View v) {
    Thread th = Thread.currentThread();
    long id = th.getId();
    Log.v(TAG, "ui id="+id);
   }
  });
  btn_not_ui1.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    lt.mHandler.post(new Runnable() {
     @Override
     public void run() {
      Thread th = Thread.currentThread();
      long id = th.getId();
      Log.v(TAG, "not ui id="+id);
     }
     
    });
    
   }
  });
  btn_not_ui2.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    lt.mHandler.post(null);
    
   }
  });
 }
 
 class LooperThread extends Thread {
  public Handler mHandler;
  public void run() {
   Log.v(TAG, "Looper.prepare()");
   Looper.prepare();
   mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
     // process incoming messages here
     Thread th = Thread.currentThread();
     long id = th.getId();
     Log.v(TAG, "LooperThread id="+id);
    }
   };
   Looper.loop();
  }
 }
}
LooperThreadクラスの中でHandlerのhandleMessageをoverrideしているけど
こいつはMessageの中にcallback(Runnableのこと)が無かったら実行される。(インスタンス生成時にデフォルトのcallbackを設定しなければの話ではあるが。)
なので、
起動してbtn_ui、btn_not_ui1、btn_not_ui2の順番にクリックすると
onCreate ui id=1 ← onCreateが呼ばれた
Looper.prepare() ← 勝手Looperの準備しました
ui id=1 ← btn_uiクリックしました
not ui id=8 ← btn_not_ui1クリックしました
LooperThread id=8 ← btn_not_ui2クリックしました
のようなLog.vが出力される。

正直なところ、こんなの知っていたからって何時使うんだろって感じではある。
ただ、AsyncTaskとかを利用するような処理をいっぱいbackgroundで走らせると
基本設計時に考えたThread構成が良くわかんない感じになりそうではある。
そんなときには、自分でworker threadを作ってそのworkerに決まった処理をpostする。みないな仕組みを自分で作るにはいいかもね。