Android - erro "não é possível transmitir transmissão" no receptor de transmissão registrado dinamicamente
Estou tentando executar uma tarefa relativamente simples: tenho um fragmento que inicia um serviço para extrair algum JSON de um servidor remoto. Desejo então passar esse JSON de volta ao fragmento de chamada original usando uma transmissão, com o BroadcastReceiver definido como uma classe anônima no fragmento.
No entanto, sempre que tento fazer isso, continuo recebendo o seguinte erro:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.roundarch.codetest, PID: 21974
android.app.RemoteServiceException: can't deliver broadcast
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
código:
public class Part3Fragment extends Fragment {
PostCodeAdapter postCodeAdapter;
ListView listView;
BroadcastReceiver receiver;
IntentFilter intentFilter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_part3, null);
initialiseReceiver();
View emptyView = (View) view.findViewById(R.id.empty_textview);
ListView listView = (ListView) view.findViewById(R.id.part3_listview);
listView.setEmptyView(emptyView);
// TODO - the listview will need to be provided with a source for data
// TODO - (optional) you can set up handling to list item selection if you wish
return view;
}
@Override
public void onResume() {
super.onResume();
initialiseReceiver();
getActivity().startService(new Intent(getActivity(), Part3Service.class));
}
public void initialiseReceiver(){
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getBundleExtra("bundle");
ArrayList<PostCodesResult.Result> postcodes = (ArrayList<PostCodesResult.Result>) bundle.getSerializable("postcodeArray");
updatePostcodes(postcodes);
}
};
intentFilter = new IntentFilter("JSON_RECEIVED");
getActivity().registerReceiver(receiver, intentFilter);
}
@Override
public void onPause() {
super.onPause();
}
private void updatePostcodes(ArrayList<PostCodesResult.Result> postcodes) {
if (postcodes.size() > 0){
postCodeAdapter = new PostCodeAdapter(getActivity(), R.layout.part3_listview_item, postcodes);
listView.setAdapter(postCodeAdapter);
postCodeAdapter.notifyDataSetChanged();
}
}
}
E aqui está o código para oserviço:
public class Part3Service extends Service {
private final String TAG = this.getClass().getSimpleName();
// TODO - we can use this as the broadcast intent to filter for in our Part3Fragment
public static final String ACTION_SERVICE_DATA_UPDATED = "com.roundarch.codetest.ACTION_SERVICE_DATA_UPDATED";
private List<Map<String, String>> data = null;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service has started");
new PostCodeRetriever().execute("http://gomashup.com/json.php?fds=geo/usa/zipcode/state/IL");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void updateData() {
// TODO - start the update process for our data
}
private void broadcastDataUpdated(String jsonString) {
Intent intent = new Intent();
intent.setAction("JSON_RECEIVED");
ArrayList<PostCodesResult.Result> postcodes = new ArrayList<>();
if (jsonString != null) {
Gson gson = new Gson();
PostCodesResult result = gson.fromJson(jsonString, PostCodesResult.class);
postcodes.addAll(result.getResult());
}
Bundle bundle = new Bundle();
bundle.putSerializable("postcodeArray", postcodes);
intent.putExtra("bundle", bundle);
sendBroadcast(intent);
stopSelf();
}
class PostCodeRetriever extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
Uri uri = Uri.parse(params[0]);
String jsonString = "";
try {
URL postcodesUrl = new URL(uri.toString());
InputStream inputStream = null;
HttpURLConnection connection = (HttpURLConnection) postcodesUrl.openConnection();
connection.connect();
inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
stringBuilder.deleteCharAt(0);
stringBuilder.deleteCharAt(stringBuilder.length() -1);
jsonString = stringBuilder.toString();
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonString;
}
@Override
protected void onPostExecute(String jsonString) {
broadcastDataUpdated(jsonString);
super.onPostExecute(jsonString);
}
}
}
Eu tentei muitas coisas diferentes: enviando apenas a string JSON bruta por meio da intenção, definindo o receptor de transmissão como uma classe separada, convertendo o JSON em um ArrayList serializado e enviando isso através da intenção e, finalmente, tentando incluir tudo isso um pacote e enviando isso.
O estranho é que códigos muito semelhantes parecem funcionar bem para meus colegas de classe - não vejo diferenças entre o código e o código que possam estar causando o problema (e nem eles). Além disso, se eu tentar enviar uma String diferente através da intenção, isso parece funcionar bem - o receptor de transmissão a captura e onReceive é chamado como deveria ser. O erro "Não é possível entregar a transmissão" parece ocorrer apenas ao tentar entregar esse conjunto de dados específico e apenas para mim!