2013年2月4日月曜日

DownloadManagerのDOWNLOAD_COMPLETEアクションに対応するBroadcastReceiverを書いていてふと疑問に思ったこと

DownloadManagerのDOWNLOAD_COMPLETEアクションに対応するBroadcastReceiverを書いていて、ふと疑問。

DownloadManagerはシステムレベルで提供されているので、DOWNLOAD_COMPLETEアクションが発生した場合、自分のアプリだけにかかわらず、対応するアプリ全てにアクションがブロードキャストされるのではないかと。

そうだとしたら、フィルタリングする何らかの処理を書いておかないと、他のアプリが叩いたDownloadManagerのDOWNLOAD_COMPLETEアクションに対しても、自分のアプリのBroadcastReceiverが起動してしまうのではないかと。


試しに、DOWNLOAD_COMPLETEアクションに対応するBroadcastReceiverの記述を持つアプリをコピーして、それぞれのアプリをインストール。DOWNLOAD_COMPLETEアクションに対応して両方のBroadcastReceiverが起動するのか確認してみた。

DownlaodManagerにキュー入れする部分のコード。
Request req = new Request(uri);
req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
req.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, subPath);
req.setMimeType(contentType);
req.setTitle(getResources().getString(R.string.app_name));
req.setDescription(getResources().getString(R.string.dl_start_str));
Log.v(getTag(), "ダウンロード開始:" + uri);

//ダウンロードマネージャにダウンロードリクエストをキュー
DownloadManager dlman = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dlman.enqueue(req);

DOWNLOAD_COMPLETEアクションをレシーブするDownloadManagerBroadcastReceiverクラス。
public class DownloadManagerBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

  // 関係のあるメッセージがどうか調べる
  String pkg = intent.getPackage();
  if (pkg.equals("my.app.package")) {
       Log.v(getTag(), "関係あるブロードキャスト受信:" + intent);
  } else {
       Log.v(getTag(), "無関係なブロードキャスト受信:" + intent);
       return;
  }

} // onReceive

} // class

my.app.packageのAndroidManifest.xml抜粋




 


my.app.package_dummyのAndroidManifest.xml抜粋






my.app.package_dummyのDownloadManagerBroadcastReceiverクラス。
public class DownloadManagerBroadcastReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {

    // 関係のあるメッセージがどうか調べる
    String pkg = intent.getPackage();
    if (pkg.equals("my.app.package_dummy")) {
       Log.v(getTag(), "関係あるブロードキャスト受信:" + intent);
    } else {
       Log.v(getTag(), "無関係なブロードキャスト受信:" + intent);
       return;
    }

  } // onReceive

} // class


結果、my.app.packageでDOWNLOAD_COMPLETEアクションが発生した場合は、my.app.package.DownloadManagerBroadcastReceiverが起動、

関係あるブロードキャスト受信:Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=my.app.package cmp=my.app.package/.DownloadManagerBroadcastReceiver (has extras) }


my.app.package_dummyでDOWNLOAD_COMPLETEアクションが発生した場合は、my.app.package_dummy.DownloadManagerBroadcastReceiverが起動した。

関係あるブロードキャスト受信:Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=my.app.package_dummy cmp=my.app.package_dummy/.DownloadManagerBroadcastReceiver (has extras) }


両方のDownloadManagerBroadcastReceiverが同時に起動することはなかった。

つまり、それぞれのアプリ内でDownloadManagerを使ってダウンロードした時に発生するDOWNLOAD_COMPLETEアクションには、それぞれのマニフェストに明記しているBroadcastReceiverクラスが対応することになる。


onReceive()内でパッケージ名をチェックする必要などはない。

ということがわかった。


では、さらに、同一パッケージ内で、DOWNLOAD_COMPLETEアクションに対応するBroadcastReceiverが複数登録されていたらどうなる?というテストをしてみた。

AndroidManifest.xml抜粋





        






02-04 16:23:35.943: V/DownloadManagerBroadcastReceiver.onReceive:42(1695): 関係あるブロードキャスト受信:Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=my.app.package cmp=my.app.package/.DownloadManagerBroadcastReceiver (has extras) }
02-04 16:23:36.033: V/DownloadManagerBroadcastReceiver2.onReceive:42(1695): 関係あるブロードキャスト受信:Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=my.app.package cmp=my.app.package/.DownloadManagerBroadcastReceiver2 (has extras) }

両方のBroadcastReceiverが呼ばれた。起動順序はマニフェストに記述した順序かな?