アプリの多重起動を防ぎたい。

14,962 views
Skip to first unread message

den

unread,
Feb 17, 2011, 1:12:19 AM2/17/11
to 日本Androidの会
こんにちは!!

Androidアプリケーションを作って、適当なサーバにapkをアップロードしてテストしているのですが、以下の手順でアプリが多重起動してしまいま
す。これを防ぎたいです。ご存知の方がいらっしゃれば、お教えいただけませんでしょうか。

[その辺のサーバからのインストールの場合]
1. apkをSDカードにダウンロード、それをインストール。
2. インストール完了後画面から「開く」をタップしてアプリを起動
3. 起動したアプリのアクティビティを表示したまま、ホームボタンでホーム画面へ
4. ホーム画面から、また同じアプリを起動(上記2で起動したアクティビティとは別で新規でアクティビティが起動されてしまう)
5. 上記4で起動したアプリのアクティビティをバックボタンなどで終了させても、上記2で起動したアプリ(のアクティビティ)が表示される。

※Android Marketで配布されているアプリでも同様の現象が起こるアプリが多々ありました。
[Android Marketからのインストールの場合]
1. Android Marketからインストール。
2. インストール後、Notificationに出ているインストール完了通知から、アプリを起動
3. 起動したアプリのアクティビティを表示したまま、ホームボタンでホーム画面へ
4. ホーム画面から、また同じアプリを起動(上記2で起動したアクティビティとは別で新規でアクティビティが起動されてしまう)
5. 上記4で起動したアプリのアクティビティをバックボタンなどで終了させても、上記2で起動したアプリ(のアクティビティ)が表示される。

田代透

unread,
Feb 17, 2011, 5:36:47 AM2/17/11
to android-g...@googlegroups.com
マニフェストで android:launchMode で設定すればできるかと思いますよ。
singleTopあたりを使えばよいのではないですか

2011年2月17日15:12 den <d...@isana.net>:

> --
> このメールは Google グループのグループ「日本Androidの会」の登録者に送られています。
> このグループに投稿するには、android-g...@googlegroups.com にメールを送信してください。
> このグループから退会するには、android-group-j...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-group-japan?hl=ja からこのグループにアクセスしてください。
>
>

--
--
Toru Tashiro
toru...@gmail.com

Yasuharu Kasai

unread,
Feb 17, 2011, 7:44:30 AM2/17/11
to android-g...@googlegroups.com
denさん、

こんにちは。笠井です。

ホーム画面からのアプリ起動は、ソースコードを見ればわかりますが、intentに
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED と Intent.FLAG_ACTIVITY_NEW_TASKを
セットしています。

で、起動「される」側アプリのMAINに設定されているActivitylaunchModeがsingleInstanceやsingleTaskに
設定されていると、そのActivity(アプリを起動したときの初期画面)が表示されてしまいます。
launchModeがstandardやsingleTopに設定されていれば前回表示したアプリのままの状態で
最前面に上がってきます。

denさんがお望みの動作はおそらくこれだと思います。

アプリケーションによっては、launchModeがsingleInstanceやsingleTaskに設定されているものも
当然あるでしょう。それらのアプリはdenさんのおっしゃる
「前回起動したアクティビティとは別で新規でアクティビティが起動されてしまう」
という現象になるでしょうし、standardやsingleTopに設定されていれば新たなインスタンスを生成
することなく、前回表示した状態のアプリを最前面に持ってくるという動作になります。

ただし、これはAndroid標準のホーム画面から起動した場合にはそうなりますが、サードパーティ製の
ホームスクリーンアプリを導入した場合にはこの限りではありません。
(起動するときのintentへのフラグ設定やカテゴリ設定などに影響されますので)

パンテオン・モバイル・システムズ株式会社
笠井


2011年2月17日15:12 den <d...@isana.net>:

den

unread,
Feb 18, 2011, 4:25:40 AM2/18/11
to 日本Androidの会
田代さん、笠井さん
こんにちは!でんです。

ご回答ありがとうございました!!

私の説明不足で申し訳ないのですが、アプリのファーストアクティビティの
LaunchModeはstandardになっています。
ですので、通常のHomeアプリから起動する際に、すでに起動済みのアプリが
存在していれば、それが前面に出てきてくれて、多重起動はしませんので問題なしです。
しかし、インストール後、Notificationに出ているインストール完了通知から、
アプリを起動すると、そのアクティビティが残っている限り、あとからHome
アプリから起動したものが、全て別タスクとして起動されてしまい、アプリが
多重起動になってしまいます。
それがAndroidの仕様ということであれば、しかたないのですが。。。

具体的にご説明すると、インストール完了のNotificationからアプリ起動すると
以下のような形で起動されます。
PackageManager pm = getPackageManager();
Intent i = pm.getLaunchIntentForPackage( "パッケージ名" );
startActivity( i );
finish();
この起動したアクティビティを残したまま、Homeアプリなどから同じアプリを
起動すると、全て別タスクで起動されてしまい、いくつでも多重起動できてしまいます。

Yasuharu Kasai

unread,
Feb 18, 2011, 10:12:09 AM2/18/11
to android-g...@googlegroups.com
でんさん、

笠井です。
こちらこそすみません。
思い込みで回答してしまいました...。

試してみたところ、おっしゃる通りの動作になりました。
確かにいくつでも多重起動できてしまいますね。びっくりです。
PackageManager#getLaunchIntentForPackage()でintentにどんな設定をしてるんでしょうね。
(ソースを見れば一発でしょうけど)

非常に興味深いので、時間があるときにもっと解析してみたいです。
でんさんも何かおわかりになったら教えてください。

笠井@お役に立てず申し訳ありませんでした。


2011年2月18日18:25 den <d...@isana.net>:

den

unread,
Feb 21, 2011, 3:13:42 AM2/21/11
to 日本Androidの会
笠井さん

でんです。

またまた返信ありがとうございます!

確かにソース見れば起動方法はわかりそうですねー。
ただ、回避はソース見ても難しいんだろうなと判断し、
今回は急ぎでしたので、暫定で以下のように対処しました。

「多重起動してしまっているアプリのうち、1つでもアプリ終了させたら、
他の多重起動してしまっているタスクも終了されるような処理を入れた。」

アプリ起動時に、多重起動しちゃっているものをkillしちゃうのも
いいかなと思ったのですが、余計なパーミッションが増えちゃうので
やめました。

皆様ありがとうございました!!
余裕あったら、追加調査してみます。

あんざいゆき

unread,
Feb 21, 2011, 3:57:10 AM2/21/11
to android-g...@googlegroups.com
あんざいです。

誤解しているようなので、、、、

>私の説明不足で申し訳ないのですが、アプリのファーストアクティビティの
>LaunchModeはstandardになっています。
>ですので、通常のHomeアプリから起動する際に、すでに起動済みのアプリが
>存在していれば、それが前面に出てきてくれて、多重起動はしませんので問題なしです。


 android:launchMode="standard" はアクティビティの
 インスタンスを複数生成することができるモードです。
 なので、standard だから多重起動しないというのは間違いです。

 launchMode については
 や、自ブログですが、

 を参考にどうぞ。

 getLaunchIntentForPackage については、
 に少し書いてあります。
 最初に CATEGORY_INFO を見て、次に CATEGORY_LAUNCHER を見て、
 両方ない場合は null を返すようです。

 笠井さんが指摘しているように、ランチャーからの起動では、
 Intent.FLAG_ACTIVITY_NEW_TASK がセットされます。
 このフラグがセットされている場合、スタートさせようとしてるアクティビティ用の
 タスクが、すでに起動されているときは、Activity を新しくスタートせずに、
 現状のタスクをスタックの前方にもってきてくれます。
 しかし、タスクが異なる場合、別のタスクとして Activity を起動します。
 
 多分、ランチャーから起動した場合と、インストール完了の notification からでは
 タスクが異なるのでしょう。

 一番簡単な方法は、アプリの Launcher Activity に android:launchMode="singleTask"
 を設定することだと思います。




2011年2月21日17:13 den <d...@isana.net>:



--
あんざい ゆき
anzai...@gmail.com
twitter : @yanzm
Y.A.Mの雑記帳 http://y-anz-m.blogspot.com/

Yasuharu Kasai

unread,
Feb 21, 2011, 5:40:13 AM2/21/11
to android-g...@googlegroups.com
あんざいさん、でんさん、

またまた笠井です。

 Launcher Activity に android:launchMode="singleTask"を設定すると、
既に起動されているTaskが使用されますが、最後に表示していたActivity
が表示される保障があるわけではなく、Launcher Activityが最前面になり
ますよね?

私はそもそもそれが問題なんだと思い込んでいましたが、でんさんの最初
投稿を見ると本当にそうなのかわからなくなってしまいました...。

ApplicationとTaskとActivityを明確に記述するのが一番良い方法だと思い
ますが、でんさんのメールの中でTask=Activityと仮定すると、あんざいさん
のおっしゃる通り、
android:launchMode="singleTask"
でいいのかも知れませんね。

笠井



2011年2月21日17:57 あんざいゆき <anzai...@gmail.com>:

den

unread,
Feb 22, 2011, 5:20:02 AM2/22/11
to 日本Androidの会
あんざいさん、笠井さん

でんです。
どうもありがとうございます!!

> >私の説明不足で申し訳ないのですが、アプリのファーストアクティビティの
> >LaunchModeはstandardになっています。
> >ですので、通常のHomeアプリから起動する際に、すでに起動済みのアプリが
> >存在していれば、それが前面に出てきてくれて、多重起動はしませんので問題なしです。
> android:launchMode="standard" はアクティビティの
> インスタンスを複数生成することができるモードです。
> なので、standard だから多重起動しないというのは間違いです。

これ、間違いですね。ご指摘ありがとうございます。

私の説明の質が悪すぎで御手数おかけしてます。色々ご説明する必要があったようです。
アプリケーション、タスク、アクティビティの意味は、一応理解しているつもりです。
もう一度ご説明させていただくと、

まず、アプリケーションの作りとして、以下のようになっています。

・画面数が多く、さらに画面遷移がとても複雑という理由から、画面遷移(startActivity)が終わったら、もとのActivityは
finishする作りにしています。(アプリ全体がそういう作り。常にタスク内は1アクティビティしか存在しない。)

・ルートアクティビティは、スプラッシュ画面です。起動準備が終わると、他のアクティビティが起動され、スプラッシュ画面のアクティビティは
finishします。

そのアプリの作りを前提として、以下の手順でタスクが複数起動してしまいます。

a. インストール後、Notificationに出ているインストール完了通知から、アプリを起動する。
起動したアクティビティは、起動処理終了後に他アクティビティを表示して、自分はfinishする。
(startActivityのIntentパラメータ:INFO/ActivityManager(1401): Starting
activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=ない
しょ })

b. 上記aのタスクが残っている限り、あとからHome アプリより起動したものが、全て別タスクとして起動されてしまう。きっとルートアクティビ
ティが無いことが原因なのでしょうね。
(startActivityのIntentパラメータ:INFO/ActivityManager(1401): Starting
activity: Intent { act=android.intent.action.MAIN
catandroid.intent.category.LAUNCHER] flg=0x10200000 cmp=ないしょ bnds81,74]
[219,232] })

お教えいただいたsingleTaskの設定も試しましたが、同様の現象が起こってしまいます。
(ルートアクティビティが無くなる作りであるためですよね。)

上記aのIntentのフラグにはFLAG_ACTIVITY_RESET_TASK_IF_NEEDEDが無いことと、
ルートアクティビティが無くなる作りであることが原因なのだと認識しています。
(標準のホームアプリから起動するぶんには、一切問題ないため)

今回の問題、Androidアプリとしてはイレギュラーな作りにしてしまったのが原因であろうことは、
いまさらですが理解しています。
画面数が多くて、画面遷移が複雑なアプリを作る上でのサンプルやガイドラインでもあれば嬉しいのですが、
今後自分たちで頑張って考えてみます。

貴重なお時間いただき、ありがとうございました!!

On 2月21日, 午後7:40, Yasuharu Kasai <pantheon.mob...@gmail.com> wrote:
> あんざいさん、でんさん、
>
> またまた笠井です。
>
> Launcher Activity に android:launchMode="singleTask"を設定すると、
> 既に起動されているTaskが使用されますが、最後に表示していたActivity
> が表示される保障があるわけではなく、Launcher Activityが最前面になり
> ますよね?
>
> 私はそもそもそれが問題なんだと思い込んでいましたが、でんさんの最初
> の投稿を見ると本当にそうなのかわからなくなってしまいました...。
>
> ApplicationとTaskとActivityを明確に記述するのが一番良い方法だと思い
> ますが、でんさんのメールの中でTask=Activityと仮定すると、あんざいさん
> のおっしゃる通り、
> android:launchMode="singleTask"
> でいいのかも知れませんね。
>
> 笠井
>
> 2011年2月21日17:57 あんざいゆき <anzai.y...@gmail.com>:
>
>
>
> > あんざいです。
>
> > 誤解しているようなので、、、、
>
> > >私の説明不足で申し訳ないのですが、アプリのファーストアクティビティの
> > >LaunchModeはstandardになっています。
> > >ですので、通常のHomeアプリから起動する際に、すでに起動済みのアプリが
> > >存在していれば、それが前面に出てきてくれて、多重起動はしませんので問題なしです。
>
> > android:launchMode="standard" はアクティビティの
> > インスタンスを複数生成することができるモードです。
> > なので、standard だから多重起動しないというのは間違いです。
>
> > launchMode については
> > 公式ドキュメントの
> >http://developer.android.com/guide/topics/fundamentals.html#lmodes
> > や、自ブログですが、
> >http://y-anz-m.blogspot.com/2011/02/androidlauchmode.html
> >http://y-anz-m.blogspot.com/2010/08/android_10.html
>
> > を参考にどうぞ。
>
> > getLaunchIntentForPackage については、
>
> >http://tools.oesf.biz/android-2.3_r1.0/xref/frameworks/base/core/java...
> > に少し書いてあります。
> > 最初に CATEGORY_INFO を見て、次に CATEGORY_LAUNCHER を見て、
> > 両方ない場合は null を返すようです。
>
> > 笠井さんが指摘しているように、ランチャーからの起動では、
> > Intent.FLAG_ACTIVITY_NEW_TASK
> > <http://developer.android.com/reference/android/content/Intent.html#FL...>
> ...
>
> もっと読む ≫
Reply all
Reply to author
Forward
0 new messages