我正在尝试执行一个相对简单的任务:我有一个片段启动服务从远程服务器中提取一些JSON.然后,我想使用广播将该JSON传递回原始调用片段,并将broadcastReceiver定义为片段中的匿名类.
但是,每当我尝试这样做时,我都会收到以下错误:
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)
码:
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(); } }}
这是服务的代码:
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); } }}
我尝试了很多不同的东西:通过intent发送原始JsON字符串,将广播接收器定义为单独的类,将JsON转换为序列化ArrayList并通过intent发送,最后尝试将其全部包含在内捆绑并发送.
奇怪的是,非常相似的代码似乎对我的同学很好 – 我看不出他们的代码和我的代码之间可能导致问题的任何差异(他们也不能).另外,如果我试图通过意图发送一个不同的字符串然后似乎工作正常 – 广播接收器选择它并且onReceive被调用它应该是.在尝试提供此特定数据集时,似乎只会出现“无法传送广播”错误,仅适用于我!
解决方法:
我知道原来的问题是在不久前发布的,但我最近遇到了这个问题,我想发布我所做的修复它,以防它帮助其他人.
我能够通过进行以下2个更改来纠正问题.我无法明确确认问题的确切原因,因此我不确定是否有必要进行这两项更改.但是,考虑到应用程序正在做什么,这些是对旧代码的改进,所以我保留了它们.
Intent动作常量的定义
该应用程序使用一个扩展IntentService的类来执行后台任务.该类定义了许多静态最终String值,这些值用作服务完成任务时广播的Intents的“action”值.
我注意到这些字符串是使用与 *** 作含义匹配的值(例如“SAVE_COMMENT”)定义的,但它们不包含应用程序的包名称.
来自AndroID的Intents和IntentFilter文档……
If you define your own actions, be sure to include your app’s package name as a prefix.
https://developer.android.com/guide/components/intents-filters.html
我更改了这些字符串的值以包含包名称.
我无法证明这一点,但我想知道其中一个动作名称是否可能与这些设备上另一个应用程序中定义的动作发生冲突.
切换到LocalbroadcastManager
应用程序在完成任务时使用Context :: sendbroadcast()来广播Intent.应用程序服务执行的所有逻辑仅适用于该应用程序,因此我将其切换为使用LocalbroadcastManager :: sendbroadcast().这使广播保持在应用程序内,进一步防止了与另一个应用程序冲突的可能性.
总结以上是内存溢出为你收集整理的Android – 在动态注册的广播接收器上收到“无法传送广播”错误全部内容,希望文章能够帮你解决Android – 在动态注册的广播接收器上收到“无法传送广播”错误所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)