Flex、AIR、Java、Androidなど

Archive for 2月, 2009

先日から作っていた端末を振ることでタスクの切り替えを行うアプリケーション、一応動くようになったのでソース貼っておきます。
※センサーの実装部分はほとんどeggさまに教えてもらった実装そのままとコピペです。いつもありがとうございます。
パッケージはこんな感じ。

ShakeAgent.javaはActivityを継承、ShakeDetectorはServiceを継承、TriggerOnBootはBroadcastReceiverを継承し、デバイスの起動時に呼ばれるクラスです。
基本的にShakeAgentの起動時、もしくは端末の起動時にShakeDetectorがstartSeviceされ、端末の非ロック時にはServiceがバックグラウンドで振動を監視し、振動を検知したらタスクを切り替えます。
一応端末の振りの強さで処理を分岐させる関数も残してありますが、とりあえず現在は強く振っても弱く振ってもタスクの切り替えを行うよう記述しています。
パッケージとソースを見てもらえれば分かるかと思うのですが、なるべく機能の追加をしやすいようにしています。例えば「強く振ったときに電話をかける画面を開きたい」など振ったときに別の処理を行いたい場合はworkerパッケージ内に適当なクラスを追加し、ShakeDetectorの実装を変えてやれば簡単にできるかと思います。
TaskSwitcherクラスは前回振られたときからの時間を測定し、短いスパンだったらタスクリストの途中のActivityを呼ぶようにしているのでShakeDetectorのコンストラクタで初期化していますが、場合によってはローカルでも、staticでもいいかもしれません。
昨日悩んでいたSecurityExceptionについては、
E/AndroidRuntime( 2269): java.lang.SecurityException: Permission Denial: starting Intent { action=android.intent.action.MAIN categories={android.intent.category.LAUNCHER} flags=0×10000000 comp={com.android.calendar/com.android.calendar.DayActivity} } from ProcessRecord{43616330 2269:biz.stachibana.ShakeAgent/10067} (pid=2269, uid=10067) requires null
というような感じでそのアプリケーションが最初に起動するActivityを取れていないのが原因ぽかったので色々やってみて、
List<ActivityManager.RunningTaskInfo> runningTasks = new ArrayList<ActivityManager.RunningTaskInfo>();



intent.setComponent(runningTasks.get(currentIndex).baseActivity);
ではなく、
List<ActivityManager.RecentTaskInfo> runningTasks = new ArrayList<ActivityManager.RecentTaskInfo>();



intent.setComponent(runningTasks.get(currentIndex).baseIntent.getComponent());
とやってやることで解決しました。
apkは以下からダウンロードできます。
※アプリケーション、プログラムを利用した事によるいかなる損害への一切の責任を負いません。ご利用は自己責任にてお願いいたします。
ShakeAgent_alpha_signed.apk
何かあればコメントにてお願いします。
では、長いですが以下に全てのソースを貼っておきます。汚いと思いますので是非つっこみをお願いしますm(_ _)m

23 2月, 2009

SecurityExceptionに苦戦中

Posted by: tachibana In: Android| プログラミング

WindowsでいうところのAlt+Tab、タスクの切り替えを端末を振ることで行うアプリケーションを作っていたのですが、特定のアプリケーションでSecurityExceptionが出てアプリが強制終了してしまいます。
まあそこ以外はほとんど出来たののですが、SecurityExceptionを投げるのはカレンダーとメール。ここらをIntentで起動しようとするとSecurityException Permission Denialなんちゃらがthrowされます。
作ろうかなと思ったのは既にAndroid MarketでリリースされているTast Switchというアプリケーションを見つけたからなのですが、こちらだとメールは問題なく起動(startActivity(intent))できているようです。
また、PCにつないで見てみたのですが、Tast Switchの方はIntentに指定するComponentがそのアプリケーションのメインに指定されているActivityですね。
でも、タスクを切り替えたからといってそのアプリケーションの初期画面が表示されるのではなく、ちゃんと一番最近表示されたActivityが表示されます。
私はタスクの切り替えは取得したRunningTaskのbaseActivityを取っているのですが、これがそのアプリケーションのメインにならないとおかしいと思うのですが、メインを取れていないようです。
TaskSwitchの方はメールに切り替える際にはcompはパッケージ名.Welcomeとかになっているのですが、私の作った方はtopActivityでなくbaseActivityをとっているにも関わらずFolderActivityとかになってしまいます。
困りました。

コメントは受け付けていません。
Tags:

2/22追記:またしてもeggさまに教えて頂いたのですが、センサの値を毎回比較するのは遅い&精度が悪いです。振られたことを検知したら一定時間の値を配列に貯めて、処理に振り分ける際に一度だけ比較した方がいいと思います。
2/20追記:eggさまにコメントで教えて頂き、振動の強弱で押下するボタンを振り分けることができるようになりました。弱く振るとメニュー、強く振るとbackボタンを押下するイベントを送信します。変更したのはShakableActivity.javaの真ん中くらいです。ありがとうございました。動画も追加しときます。
変更前:一定の強さ以上の振動を引き金に「メニューボタンが押された」イベントを送信

変更後:弱い振動でメニューボタン、強い振動でbackボタンを押下のイベントを送信

G1/Dev Phoneはメニューボタンが小さい上押しにくい位置にあり、メニューを何度も押すようなアプリケーションでは私はイライラしてしまっていました。
ので、端末を振ることで加速度センサに振動を感知させ、それでもって「押しにくいボタン押したこと」を代用するようなことができないかなと思いつき、色々見てるうちにKeyDownイベントをプログラム的に発生させることも、加速度で振動を検知することも可能なようなのでActivityを継承したShakableActivityというのを作ってみました。
加速度センサはGrandNatureさまのAndroid – 加速度センサー再び、
KeyEventの方はMy life with Android :-)さまのGenerating keypresses programmatically、
本当にありがとうございます。
ちなみに私が自分で書いたところはほぼありません(笑)。上述のお二人が書かれたソースを組み合わせただけです。
ちなみに
■ android.os.ServiceManager
■ android.view.IWindowManager
の二つはパブリックでないということですのでGenerating keypresses programmaticallyさまのとこから落とす必要があります。
それをパッケージ内に保存したらあとはActivityを継承したShakableActivityを書き、アプリケーションはActivityを継承するのではなくShakableActivityを継承させるだけです。
まあ人にもよると思いますが、
src
- android.os
- ServiceManager.java
- android.view
- IWindowManager.java
- com.example.ShakableActivity
- KeyDownGenerator.java
- ShakableActivity.java
- com.example
- 実際に利用するクラス群
というような感じになるのではないでしょうか。ShakavleActivityはKeyDownGeneratorのサブクラス、実際に利用するクラス群はShakableActivityのサブクラスです。
ソースは以下。

あるアプリケーションをスクリーンが縦の状態(G1/Dev Phoneの場合だと閉じている状態)で見ていて、何かの拍子にそのアプリケーション内でキーボードを用いて文字入力をしなければいけなくなることはよくあります。
単純なものでしたらブラウザでのブラウジング中に新たなURLの入力などですが、その際には液晶部分をずらしてキーボードを出現させることが必要になります。
この際、特に処理を記述していないアプリケーションではスクリーンは縦の状態から横向きに自動的に回転され、それに伴いAndroidは現在表示中のActivityが保持している値をリリースし、新たにリソース等から生成しなおすそうです。
これにより私が書いたアプリケーションでは縦向きスクリーンでトップ > メニュー > addまでタップし、開いたdialogのEditTextにフォーカスがある状態にしておいてもキーボードを出した際にActivityはトップ画面(そのActivityのトップです)に戻ってしまうので再びメニュー > addまでタップし直さなければなりません。
これを解消する方法がAvoiding memory leaksに載っていました。
私はポインタをまだやっていないので言葉が合っているかどうか分からないのですが、onCreateでオブジェクトを準備し、setしていくのではなく、setされる値をグローバルかつstaticに定義し、毎回呼ばれるであろうonCreateメソッド内では値ではなく参照を渡しておき、その値がnullの場合はnewし、nullでなければ保持されている値を渡すことでスクリーンの向きが変わる前の状態を復元するような方法をとるようです。
確かに最初からインストールされているアプリケーションではスクリーンの向きが変わってもActivityの状態は変わらないことが多いですし、私が書いたアプリケーションではbackボタンで戻っただけなのにListViewがズラズラと更新されたりということがありました。
まだまだ勉強ですね。
※ちなみに上記リンク先にはグローバルでstatisなフィールドを作りまくると当然メモリは食いますのでそれも考えないといけないとも書いています。

コメントは受け付けていません。
Tags:

16 2月, 2009

Dev Phone(G1)をwifiルーターに

Posted by: tachibana In: Android

ぼちぼち出来るようになってきているようですね。まあ当然でしょうが。
Tethering via WiFi – Troubleshooting – Page 44 – xda-developersの真ん中ぐらい。apkあります。
gtether GPhone Tether via WiFi 一部ソースコード公開?
個人的には
3G – G1(Dev Phone) – PC等クライアント機 よりも、Dev PhoneがAd-hocなネットワークを設定できるようになってくれた方がうれしいのですが(笑)
アメリカなどではG1は定額プランでしか売られてないのでこのあたりの事情も日本とは違うのでしょうかね。

コメントは受け付けていません。

Categories

 

2009年2月
« 1月   3月 »
 1
2345678
9101112131415
16171819202122
232425262728  

About

Author: tachibana

  • ちょっとしたことはTwitterに書いています。こっちはアプリの公開等の時に更新されます。
  • 最近はもっぱらJavaとObjective Cです。AS3は飽きました。
  • スクリプト言語ではPerlが好きでしたが最近はGAE/Jで何でもやってます。
  • Linuxは自宅サーバー建てるのがやっとのレベルです。前の会社で何日も徹夜してやったのはいい思い出です。
  • アプリへのご要望などご意見等ありましたらお気軽にご連絡下さい。

Alternative content here