How to Use "Goasync" for Broadcastreceiver

How to use goAsync for broadcastReceiver?

You can find short explanation here.

Use goAsync() if you want to handoff the processing inside of your BroadcastReceiver's onReceive() method to another thread. The onReceive() method can then be finished there. The PendingResult is passed to the new thread and you have to call PendingResult.finish() to actually inform the system that this receiver can be recycled.

For example:

final PendingResult result = goAsync();
Thread thread = new Thread() {
public void run() {
int i;
// Do processing
result.setResultCode(i);
result.finish();
}
};
thread.start();

BroadcastReceiver goAsync() returns null PendingResult

I wrote a JobIntentService instead:

package com.example.broadcastreceiverpendingintenttest;

import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.util.Log;

public class MyJobIntentService extends JobIntentService {

public static final String ACTION = "and....action!";

static final int JOB_ID = 9001;

@Override
protected void onHandleWork(@NonNull Intent intent) {
// TODO check the intent action is valid, get extras etc
Log.i("tag", "performed my task");
}
}

It's declared in AndroidManifest as follows:

<service
android:name=".MyJobIntentService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false" />

MyReceiver then enqueues work for the Service:

package com.example.broadcastreceiverpendingintenttest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Log;

public class MyReceiver extends BroadcastReceiver {

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

Intent jobIntent = new Intent();
jobIntent.setAction(MyJobIntentService.ACTION);
MyJobIntentService.enqueueWork(context, MyJobIntentService.class, MyJobIntentService.JOB_ID, jobIntent);
}
}

Bit more overhead than I wanted, but it gets the job done.

android, how to unit test BroadcastReceiver which uses doAsync()

fond a way, there must be better one tho.

        BroadcastReceiver.PendingResult pendingResultMock = 
mock(BroadcastReceiver.PendingResult.class);
NotificationReceiver receiverSpy = spy(new NotificationReceiver());
doReturn(pendingResultMock).when(receiverSpy).goAsync();

Broadcast receiver goAsync

It changes the thread so you can do computationally heavy work without freezing the UI thread. Read the docs:

" This does not change the expectation of being relatively responsive to the broadcast (finishing it within 10s), but does allow the implementation to move work related to it over to another thread to avoid glitching the main UI thread due to disk IO."

Broadcast receiver goAsync

It changes the thread so you can do computationally heavy work without freezing the UI thread. Read the docs:

" This does not change the expectation of being relatively responsive to the broadcast (finishing it within 10s), but does allow the implementation to move work related to it over to another thread to avoid glitching the main UI thread due to disk IO."

Async Task inside BroadcastReceiver onReceive method not running?

The problem is that since you are executing the Network Request using an Async Task in the onReceive method, the onReceive method returns before the AsyncTask executes since an Async Task is Asynchronous. Therefore the process that is running the onRequest method becomes a low priority since the onReceive method has returned and the operating system will kill it before your Async Task actually executes.

Here are two solutions:

First ensure that the receiver is declared in your Android manifest, then do one of the following.

  1. Instead of calling an Async Task to execute your network request, create a service and use the service to run the network code.

  2. You can call the goAsync() method in the onReceive method to tell the system to give the receiver more time to execute its Async Task. The code for this would be something like this:

    @Override
    public void onReceive(final Context context, final Intent intent) {
    //create a pending intend that you will pass to the Async task so you can tell the system when the Async Task finished so that it can recycle.
    final PendingResult pendingResult = goAsync();
    AsyncTask<String, Integer, String> asyncTask = new AsyncTask<String, Integer, String>() {
    @Override
    protected String doInBackground(String... params) {
    //put the network calling code in here

    // Must call finish() so the BroadcastReceiver can be recycled.
    pendingResult.finish();
    return data;
    }
    };
    asyncTask.execute();
    }

The second way I believe would be simpler, so I would reccomend using that as it doesnt require you to create a whole new service.



Related Topics



Leave a reply



Submit