2011/08/07

[widget]PendingIntent

過去記事:2010/08/22 18:50
PendingIntentは、newしない。
staticメソッドの以下のいずれかを使って取得する。
  • getBroadcast()
  • getActivity()
  • getService()
getBoradcast()の場合、intentの送信はブロードキャストされる。
getActivity()の場合、Activity()を起動する。
getService()の場合、Serviceを起動する。
AppWidgetの場合、PendingIntentをRemoteViewsと結びつける。
  • setOnClickPendingIntent()
これしかなかった。
つまり、AppWidgetのコントロールとPendingIntentを結びつけ、クリックされたときにIntentを発行するのだ。
他にも、AlarmManagerで、時間が経ったらIntentを発行する、という使い方もできるそうだ。

上記の3メソッドだが、とる引数は同じだ。
その中でよくわからんのが、2番目と4番目。
2番目は、requestCode。
「Private request code for the sender (currently not used)」とあるから、使ってないのか?
ソース上は、Parcelにセットされている。しかし、どこでどのように使われているのかはよくわからん。
ActivityManagerNative.getDefault().getIntentSender()の引数で渡され、Parcelに詰められ、IBinder::transact()に投げられ・・・そこからよくわからん。
Activity関係のソースには、requestCodeってのがよく出てくるので、そこと関連があるのかもしれん。
ないのかもしれん。
4番目は、flagだ。
Intent.fillIn()で使えるフラグか、PendingIntent用のフラグ4種。
  • FLAG_NO_CREATE : PendingIntentがまだないなら、nullを返す(生成しない)
  • FLAG_ONE_SHOT : 1回しか使えない。このフラグが設定されていた場合、send()が呼ばれると自動的にキャンセルされ、それ以降はこのPendingIntentを使ってsend()できない。
  • FLAG_CANCEL_CURRENT : 既にPendingIntentがあるなら、生成する前に現在のPendingIntentをキャンセルする。
  • FLAG_UPDATE_CURRENT : 既にPendingIntnetがあるなら、破棄せずにextra dataを新しいintentに置き換える。前のPendingIntentが新しいextra dataだろうと気にしなくていい場合に使える。
かなりいい加減な訳だ。。
きっちりと前のPendingIntentを破棄したい場合はFLAG_CANCEL_CURRENTを使い、どうでもいい場合はFLAG_UPDATE_CURRENTを使えばいい、ということだろうか。
たぶん、FLAG_UPDATE_CURRENTの方が軽いのだろう。
これらは、現在PendingIntentが存在するかどうかを気にしている。ということは、FLAG_XXX_CURRENTを使用した場合、PendingIntentは最後の1つだけが有効になる、と考えてよいか。
FLAG_ONE_SHOTは、send()後どうなるのだろう?
ネットで探していると、クリックイベントでFLAG_ONE_SHOTを指定した場合、連打すると落ちる、というようなことが書かれていた。
送信できないなら、無視してほしいのだが、これは今でもそうなのだろうか。
あー、例外が発生するね。
E/RemoteViews( 1955): Cannot send pending intent:

E/RemoteViews( 1955): android.content.IntentSender$SendIntentException

E/RemoteViews( 1955):   at android.app.ContextImpl.startIntentSender(ContextImpl.java:640)

E/RemoteViews( 1955):   at android.widget.RemoteViews$SetOnClickPendingIntent$1.onClick(RemoteViews.java:157)

E/RemoteViews( 1955):   at android.view.View.performClick(View.java:2408)

E/RemoteViews( 1955):   at android.view.View$PerformClick.run(View.java:8816)

E/RemoteViews( 1955):   at android.os.Handler.handleCallback(Handler.java:587)

E/RemoteViews( 1955):   at android.os.Handler.dispatchMessage(Handler.java:92)

E/RemoteViews( 1955):   at android.os.Looper.loop(Looper.java:123)

E/RemoteViews( 1955):   at android.app.ActivityThread.main(ActivityThread.java:4627)

E/RemoteViews( 1955):   at java.lang.reflect.Method.invokeNative(Native Method)

E/RemoteViews( 1955):   at java.lang.reflect.Method.invoke(Method.java:521)

E/RemoteViews( 1955):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)

E/RemoteViews( 1955):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)

E/RemoteViews( 1955):   at dalvik.system.NativeStart.main(Native Method)
まあ、死にはしないから、いいか(いいのか?)。
引数のintentは、Intent.fillIn()を使ってコピーされるのだろう。
と思ったが、これはcontentsのコピーをするらしい。
intent自身のコピーではないのは何でだろう。。。
理由はあるのだろうが、推測できるような知識がありません。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。