質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

1069閲覧

Workerのタスクの状態がSucceededなのに、なぜブロードキャストを受信できるのでしょうか?

firstlast

総合スコア138

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2021/11/23 13:37

編集2021/11/23 13:49

宜しくお願いします。

#背景
画面から送信したブロードキャストをタスクで受信して、画面からタスクに特定の処理をさせようと思いました。

#試してみた事
Worker[*1]クラスを拡張したクラスをつくり、そのクラスにDoWorkメソッドを追加し、そこにブロードキャストレシーバーを登録する処理をコーディングしました。
このアプリを動作させてみると、希望通り、画面から送信したブロードキャストをタスクで受信することができました。
*1 androidx.work.Worker

#疑問点
画面からブロードキャストする直前に、android studio のapplication inspectionでタスクの状態を確認したところ、Succeededと表示されていました。(下の画像)
Succeededが表示されているということは、タスクが完了していると考えるのが妥当だと思うのですが、なぜ、ブロードキャストを受信することができるのでしょうか?
イメージ説明

#補足
###画面
イメージ説明
①タスク登録ボタン と ②ブロードキャストボタン が配置されています。

###処理
#####①タスク起動ボタン押下時
Workerクラスを拡張したTestWorkerクラスを指定してenqueueUniqueWorkを実行します。

#####②ブロードキャストボタン押下時
LocalBroadcastManagerのsendBroadcastメソッドを実行します。
このブロードキャストは①で起動されたタスクで受信できるようになっています。

##問題再現手順
①タスク起動ボタンを押します。タスクの内容はスカスカなのですぐ終わるはずです。
念のため、application inspectionでタスクの状態を確認します。Succeeded となっています。
続いて、②ブロードキャストボタンを3回押してみます。

###実行結果
#####タスク登録時

クラスメソッドログ
MainActivity$1 onClick          ===>: 「タスク登録」ボタンが押されました。タスクをキューに登録します。
TestWorker <init>               ===>: thread id:36
TestWorker doWork               ===>: thread id:44
TestWorker setBroadcastReceiver ===>: ブロードキャストレシーバーのインスタンスを作成します。
TestWorker  doWork               ===>: ブロードキャストレシーバーを登録します。

#####ブロードキャスト受信時

クラスメソッドログ
MainActivity$2onClick          ===>: 「ブロードキャスト」ボタンが押されました。ブロードキャストします。
TestWorker$1  onReceive          ===>: ブロードキャストレシーバーが反応しました。アクションは、[firstlast20180521.workerobjectwithbroadcastreceiver.BR_ACTION_CONTACT_WORKER]です。
TestWorker$1 onReceive           ===>: ★☆★☆アクティビティからブロードキャストを受信しました。☆★☆★ count ===>[100]
MainActivity$2 onClick           ===>: 「ブロードキャスト」ボタンが押されました。ブロードキャストします。
TestWorker$1 onReceive          ===>: ブロードキャストレシーバーが反応しました。アクションは、[firstlast20180521.workerobjectwithbroadcastreceiver.BR_ACTION_CONTACT_WORKER]です。
TestWorker$1 onReceive          ===>: ★☆★☆アクティビティからブロードキャストを受信しました。☆★☆★ count ===>[101]
MainActivity$2 onClick          ===>: 「ブロードキャスト」ボタンが押されました。ブロードキャストします。
TestWorker$1 onReceive          ===>: ブロードキャストレシーバーが反応しました。アクションは、[firstlast20180521.workerobjectwithbroadcastreceiver.BR_ACTION_CONTACT_WORKER]です。
TestWorker$1 onReceive          ===>: ★☆★☆アクティビティからブロードキャストを受信しました。☆★☆★ count ===>[102]

###ソースコード
####MainActivity.java

java

1m_enqueueWorkerButton.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 Debug.print("「タスク登録」ボタンが押されました。タスクをキューに登録します。"); 5 OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(TestWorker.class).build(); 6 WorkManager.getInstance(MainActivity.this).enqueueUniqueWork(WORKER1, ExistingWorkPolicy.REPLACE, request); 7 8 } 9}); 10 11m_broadcastButton.setOnClickListener(new View.OnClickListener() { 12 @Override 13 public void onClick(View v) { 14 Debug.print("「ブロードキャスト」ボタンが押されました。ブロードキャストします。"); 15 Intent intent = new Intent(); 16 intent.setAction(BR_ACTION_CONTACT_WORKER); 17 m_localBroadcastManager.sendBroadcast(intent); 18 19 } 20});

####TestWorker.java

java

1package firstlast20180521.workerobjectwithbroadcastreceiver; 2 3import android.content.BroadcastReceiver; 4import android.content.Context; 5import android.content.Intent; 6import android.content.IntentFilter; 7 8import androidx.annotation.NonNull; 9import androidx.localbroadcastmanager.content.LocalBroadcastManager; 10import androidx.work.Worker; 11import androidx.work.WorkerParameters; 12 13import firstlast20180521.workerobjectwithbroadcastreceiver.utilities.Debug; 14 15public class TestWorker extends Worker{ 16 17 //ブロードキャストマネージャー 18 private LocalBroadcastManager m_localBroadcastManager; 19 20 //ブロードキャスト(受信) 21 private BroadcastReceiver m_broadcastReceiver; 22 23 private int m_count; 24 25 //コンストラクター 26 public TestWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { 27 super(context, workerParams); 28 29 Debug.print("thread id:" + Thread.currentThread().getId()); 30 m_localBroadcastManager = LocalBroadcastManager.getInstance(getApplicationContext()); 31 32 m_count = 100; 33 34 } 35 36 @NonNull 37 @Override 38 public Result doWork() { 39 Debug.print("thread id:" + Thread.currentThread().getId()); 40 41 setBroadcastReceiver(); 42 43 Debug.print("ブロードキャストレシーバーを登録します。"); 44 IntentFilter filter = new IntentFilter(); 45 filter.addAction(MainActivity.BR_ACTION_CONTACT_WORKER); 46 m_localBroadcastManager.registerReceiver(this.m_broadcastReceiver, filter); 47 48 return Result.success(); 49 } 50 51 @Override 52 public void onStopped() { 53 super.onStopped(); 54 55 Debug.print("---------------------------------->>>>thread id:" + Thread.currentThread().getId()); 56 57 } 58 59 private void setBroadcastReceiver() { 60 Debug.print("ブロードキャストレシーバーのインスタンスを作成します。"); 61 62 this.m_broadcastReceiver = new BroadcastReceiver(){ 63 64 @Override 65 public void onReceive(Context context, Intent intent) { 66 String action = intent.getAction(); 67 68 Debug.print(String.format("ブロードキャストレシーバーが反応しました。アクションは、[%s]です。", action)); 69 70 if(action.equals(MainActivity.BR_ACTION_CONTACT_WORKER)){ 71 Debug.print(String.format("★☆★☆アクティビティからブロードキャストを受信しました。☆★☆★ count ===>[%d]", m_count++)); 72 73 } 74 75 } 76 }; 77 } 78}

以上

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/11/23 14:04

ボタンのクリックリスナを「登録」したらその瞬間に「実行」されるでしょうか? 「登録」と「実行」が関係無いのは当然でしょう。
firstlast

2021/11/23 14:17 編集

回答ありがとうございます。 私の認識も、jimbeさんと同じで、登録したリスナは、ボタンを押したタイミングで実行されるという認識です。実行結果のログもそういう風になっていると思います。
firstlast

2021/11/24 15:49

回答ありがとうございます。 頂いたリンクを含めて、いろいろ調べてみる必要がありそうです。
hoshi-takanori

2021/11/25 01:15

WorkInfo.State の状態遷移図はここにありますね。そして、私の上のコメントはなんか勘違いしてましたが、WorkInfo.State は個々のタスクの状態なので、SUCCEEDED になったらそれでおしまい (なので READY ではない) ですね。ごめんなさい。 https://developer.android.com/topic/libraries/architecture/workmanager/how-to/states-and-observation?hl=ja そして、コードをよく見たら、Worker でやってる処理はリスナーを登録するだけなので、すぐ終了して SUCCEEDED になるのでしょうね。その後のブロードキャストの処理は Worker とは無関係ってことなのでは…。
firstlast

2021/11/25 04:11 編集

回答ありがとうございます。 ソースコードの要所要所に、プロセスIDとスレッドIDを表示させてみたところ、ブロードキャストの受信処理onReceiveとMainActivityのonCreate処理が同じプロセス、同じスレッドになっていました。
firstlast

2021/11/25 04:13

そして、TestWorkerのdoWorkは、同じプロセス、別スレッドでした。
hoshi-takanori

2021/11/25 04:16

プロセスやスレッドの話ではなく、Worker の管理下で動いてるコードかどうかという話をしてるつもりです。
firstlast

2021/11/25 06:16

回答ありがとうございます。 succeededになったあとに、アクセスできているメモリ空間はいったい何が管理しているものなのか という疑問は残りましたが、 あまり突き詰めてもきりがないので、ここらへんで締めたいと思います。
guest

回答1

0

自己解決

タスクがキューに登録され実行されると、TestWorkerのインスタンスがどこかに生まれ、doWorkメソッドの処理がsucceededになった後でも、TestWorkerのインスタンスはそのまま残っていて、そこにあるブロードキャストレシーバーオブジェクトにアクセスできる。

という浅い理解で、納得しておきたいと思います。

投稿2021/11/25 06:36

編集2021/11/25 06:44
firstlast

総合スコア138

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問