onReceive()内の処理について(別スレッド処理について)

5,434 views
Skip to first unread message

karamu

unread,
Oct 11, 2013, 2:34:47 AM10/11/13
to android-g...@googlegroups.com


karamuです。
よろしくお願いします。

BroadcastReceiverについて勉強しています。
onReceive()内では時間がかかるような処理をすべきではなく、
別スレッド上で行うべきとのことでした。

そこで質問させてください。
karamuはしばしばHandlerなどを使っているのですが、
皆様はonReceive()で重い処理をする場合、どのようにして実施なさっているのでしょうか?

スレッドといえばAsyncTaskも…と思ったのですが
AsyncTaskとHandlerではどのように使い分けされていますでしょうか?

Hirokazu Fukami

unread,
Oct 11, 2013, 2:39:38 AM10/11/13
to android-g...@googlegroups.com
こんにちはfkmです

handlerでの処理は、非同期のように見えますが、実際はUIスレッドで処理されます。
それに対し、AsyncTaskはdoInBackground()内は別スレッドで処理されます。

試しに、handlerに渡すRunnable内で時間のかかる処理(もしくはThread.sleep()で止めてみる)をやらせてみてください。

2013/10/11 karamu <karamuk...@gmail.com>:
> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com
> にメールを送信します。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
> その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
-------------------------------------------------------------
深見 浩和(Hirokazu Fukami)

URI:http://www.fkmsoft.jp
email: f...@fkmsoft.jp

Hirokazu Fukami

unread,
Oct 11, 2013, 2:41:52 AM10/11/13
to android-g...@googlegroups.com
すいませんhandlerは前提があります。
HandlerインスタンスをUIスレッド(例えばonCreate()内)で生成した場合は、
引数で渡すRunnableはUIスレッドで実行されます。


2013/10/11 Hirokazu Fukami <fkm...@gmail.com>:

Makoto Yamazaki

unread,
Oct 11, 2013, 3:29:23 AM10/11/13
to android-g...@googlegroups.com
zaki です。

単に UIスレッド以外で何か重い処理をしたいだけであれば ExecutorService も使います。
これは Android というより Java にある API ですがわりと便利ですよ。 


2013/10/11 karamu <karamuk...@gmail.com>

--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com にメールを送信します。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
YAMAZAKI Makoto

Shigeo Mutoh

unread,
Oct 11, 2013, 7:14:19 AM10/11/13
to android-g...@googlegroups.com
武藤です。

BroadcastReceiverからserviceを立ち上げる、が定石だと思います。

別スレッド上で作業を行えるケースは、このプロセスが当面死なない
という前提がなければなりません。

BroadcastReceiverはその名の通り、誰かが該当intentをbroadcastすると
突然呼び出されるわけで、その場合起動されたプロセスは極めて短命です。
このケースでHandlerにpostしようがThreadをnewしようが、とっとと
殺されてしまい、作業を行えません。

なので定石はServiceを起動して作業を行う、だと思います。


Makoto Yamazaki

unread,
Oct 11, 2013, 7:56:58 AM10/11/13
to android-g...@googlegroups.com
zaki です。

武藤さんの Service で思い出しましたが、IntentService もよく使いますね。
単に Service を使うだけでは別スレッドが走るわけではないので結局なんらかの方法でスレッドを
作って処理を投げる必要が出てきますが、 IntentService はIntentService クラスを継承して
onHandleIntent をオーバーライドして処理を書いておくだけで、そのあたりの処理をよろしく
やってくれます。あとは、 onReceive() から サービスに Intent を投げるだけでバックグラウンド処理が
完成です。

おすすめなのでぜひ使ってみてください。


2013/10/11 Shigeo Mutoh <tmh...@gmail.com>
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com にメールを送信します。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
YAMAZAKI Makoto

Shigeo Mutoh

unread,
Oct 11, 2013, 9:09:40 AM10/11/13
to android-g...@googlegroups.com
武藤です。

たしかにIntentServiceはよく使いますね。
# ただ名前がなんでやねんっ、てつっこみたくなりますが。。

このへんどうするかは設計意図によると思いますが、main(UI) threadとworker thread
の違いを理解して、どのように使うかという話だと思います。

ちょっと分類してみます。

・main(UI) thread系
- onCreateなんかが呼ばれるスレッド
- HandlerがRunnableを動かすスレッド
- onReceiveも当然そう
注意点:あまり長い処理をしてはいけない。ぶっ殺されるし、UIが止まる。

・worker thread系
- IntentServiceを使った処理
- AsyncTaskを使った処理
- new Threadした処理
- 他にもいろいろあると思う
注意点:ViewなどのUIへのアクセスが不可。

それからBroadcastReceiverの寿命、Serviceの寿命などを理解して、実装すると。

なんかAndroidって難しいですね。ははは。

yuka2py

unread,
Oct 11, 2013, 7:44:55 PM10/11/13
to android-g...@googlegroups.com
ゆかです。

おはようございます。北神戸は晴天です。 (*'-'*)
トピックと関連が薄いですが、気になったので教えてください!

BroadcastReceiver について、次のようなお話がありました。

> BroadcastReceiverはその名の通り、誰かが該当intentをbroadcastすると
> 突然呼び出されるわけで、その場合起動されたプロセスは極めて短命です。
> このケースでHandlerにpostしようがThreadをnewしようが、とっとと
> 殺されてしまい、作業を行えません。

このような認識は持っていなかった…つまり、BroadcastReceiver 内でも、
Thread 作ったら、通常は破棄されず、その処理を全うするものと思ってい
ました…(デーモンなら分かりませんが)。

この認識は誤りでしょうか?

よろしくお願いいたします!

-- ゆか

Shigeo Mutoh

unread,
Oct 12, 2013, 12:48:00 AM10/12/13
to android-g...@googlegroups.com
武藤です。

(13/10/12 8:44), yuka2py wrote:
> このような認識は持っていなかった…つまり、BroadcastReceiver 内でも、
> Thread 作ったら、通常は破棄されず、その処理を全うするものと思ってい
> ました…(デーモンなら分かりませんが)。
>
> この認識は誤りでしょうか?

その認識は誤りです。

以下urlのReceier Lifecycleのところに書いてあります。
http://developer.android.com/reference/android/content/BroadcastReceiver.html

要約すると、onReceiveを抜けたら殺すから非同期処理するな、って書いてあります。

Receiver Lifecycle

A BroadcastReceiver object is only valid for the duration of the call to
onReceive(Context, Intent). Once your code returns from this function, the
system considers the object to be finished and no longer active.

This has important repercussions to what you can do in an onReceive(Context,
Intent) implementation: anything that requires asynchronous operation is not
available, because you will need to return from the function to handle the
asynchronous operation, but at that point the BroadcastReceiver is no longer
active and thus the system is free to kill its process before the asynchronous
operation completes.

In particular, you may not show a dialog or bind to a service from within a
BroadcastReceiver. For the former, you should instead use the
NotificationManager API. For the latter, you can use Context.startService() to
send a command to the service.

私自身、receiverの中でthreadをnewした処理を行って、見事に殺されて「あれ?」と
思った経験があります。それは突然グサっと殺されるため、これをバグと思い込み
追うのは大変な徒労となります。この件では知識が重要です。

何時殺されるのかは明確でないので、もしかするとちゃんと動いているように見える
こともあろうかとは思いますが、それは運が良かっただけです。

では。

Makoto Yamazaki

unread,
Oct 12, 2013, 1:08:26 AM10/12/13
to android-g...@googlegroups.com
zaki です。

プロセスをどのようなルールに基づいて殺すかについては以下が包括的なドキュメントです。


例えばAndroidManifest.xml にreceiver タグで BOOT_COMPLETED を受信するように記述した場合
BOOT_COMPLETED を onReceive で処理している最中は優先度1(最高) ですが、return
した瞬間に優先度5(最低)に変わっていつ殺されてもおかしくない状態になります。
1から5までを読むとわかりますが、スレッドが実行中かどうかはプロセスの優先度に影響を
与えないので onReceive で new Thread して start しても onReceive から return してしまえば
プロセスごと殺されてしまう可能性があります。


2013/10/12 yuka2py <yuk...@gmail.com>
--
このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、android-group-j...@googlegroups.com にメールを送信します。
このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
http://groups.google.com/group/android-group-japan からこのグループにアクセスしてください。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。



--
YAMAZAKI Makoto

Shigeo Mutoh

unread,
Oct 12, 2013, 1:08:58 AM10/12/13
to android-g...@googlegroups.com
武藤です。

この際なので拙作を紹介させていただきます。
以前は100円だったのですが、あまりに売れないので無料にしました。
無料でもほとんど誰もダウンロードしていません。

StressRoboと言って、単にメモリを食いまくっては開放することを繰り返します。
いわゆるLOW MEMORY状態を意図的に実際に引き起こし、OSが殺人鬼に
なるよう仕向けます。
https://play.google.com/store/apps/details?id=jp.tmhouse.StressRobo&hl=ja

このアプリは主にServiceが再起動した場合のテストを行う目的で作りました。
ですが今回のようにBroadcastReceiverが正しく動作するかのテストも行う
ことができると思います。

ただ、稀にStressRoboによって端末がrebootしてしまうことがあります。
原因はOS内のバグだろうと思っています。私のせいじゃありません。

では。

karamu

unread,
Oct 15, 2013, 12:20:20 AM10/15/13
to android-g...@googlegroups.com

みなさま

たくさんのアドバイスありがとうございます。
Android初心者で(初心者というのもおこがましいくらい)
javaもAndroidと一緒に手探り感まんさいで勉強中ですが
大変勉強になりました。
IntentService、さっそく使ってみたいと思います。

武藤さんの分類説明も大変勉強になりました。
ありがとうございます。

安藤玲生

unread,
Apr 25, 2014, 4:15:17 AM4/25/14
to android-g...@googlegroups.com
レオです。

BroadcastReceiver内で 別スレッドで何かを動かすなんて聞いたことないですね。

BroadcastReceiver ⇒ IntentService

IntentService#onHandleIntent()内で重たい処理を実行してみてはどうでしょうか?

IntentService#onHandleIntent()は別スレッドで動きます。
. \\\///
. / \
. | \\ // |
. ( | (.) (.) |)
----------o00o--(_)--o00o-----------------

Mail: android....@gmail.com

-----------ooo0-------------------------------
. ( ) 0ooo
. \ ( ( )
. \_) ) /
. (_/
--

Reply all
Reply to author
Forward
0 new messages