sendBroadcast(intent) 给出空指针异常
这是我今天的第二篇文章,因为修复第一篇文章导致了另一个我正在努力解决的问题。我想使用广播和意图将数据包从服务发送回 UI。我成功绑定并启动了服务 如果您需要历史记录和代码,请参阅我的另一篇文章
空指针服务内的 sendBroadcast() 出现异常。在将 UI 绑定到服务之后,服务类确实会重新调用其构造函数。这种情况发生在另一个类中,因此无法轻松使用 Context。所以我猜 sendBroadcast 无处可去:( 我怀疑这是我的问题...初始绑定后重新调用服务构造函数。我有 onDestroy、onPause 和 onResume 覆盖了绑定和解除绑定。 任何想法或建议都会很棒,或者也许我只是犯了这个错误还有其他方法吗?
编辑 之前的绑定问题现已解决,由于我是论坛新手,接受答案略有延迟......抱歉。
类图是这样的(是移植的C#代码)
Activity doBind (on Curve.class)---> Activity 启动一个工作类(不被视为服务)Comm.class,其中包含一些通信的处理程序 -->通讯社开始了另一个工人阶级 -->之前的worker类最终调用了new Curve.class。
在 Curve.class 的最后一个阶段,sendBroadcastReceiver() 会抛出一个空指针引用,因为绑定器丢失了。 我只用一个简单的计时器测试了广播接收器,删除了中间的工作类,它工作得很好。当稍后在层次结构中进一步调用 Curve.class 并且活页夹被清空或“丢失”时,问题就开始了。
我从 Curve 中删除了除 onBind() 之外的所有活页夹引用。这可能不是一个好主意。同样,如果与直接从 UI 启动的简单计时器一起使用(没有其他工作器类),下面的代码确实可以工作。
这里还有一些代码: 服务
public class Curve extends Service
{
private NewCurvePointEventArgs newpoint = null;
private static final String TAG = "Curve";
Intent intent;
int counter = 0;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
IBinder mBinder = new LocalBinder<Curve>(this);
return mBinder;
}
@Override
public void onStart(Intent intent, int startId) {
}
@Override
public void onDestroy() {
}
public Curve(){
}
private void refreshintent(NewCurvePointEventArgs tmp)
{
ArrayList<String> thepoint = new ArrayList<String>();
thepoint.add()//various things added here
Bundle bundle = new Bundle();
// add data to bundle
bundle.putStringArrayList("New_Point", thepoint);
intent = new Intent();
intent.setAction(NEWCURVE_POINT);
intent.putExtra("NEW_POINT", bundle
sendBroadcast(intent);
}
活动现在有此代码。 doBind() 在 Activity 的 onCreate 之后调用。
private BroadcastReceiver CurveReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Curve.NEWCURVE_POINT)) {
displaynewpoint(intent);
}
}
};
private ServiceConnection CurveServiceConncetion = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
CurveService = ((LocalBinder<Curve>) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
CurveService = null;
}
};
@Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
}
@Override
public synchronized void onPause() {
super.onPause();
if(D) Log.e(TAG, "- ON PAUSE -");
}
@Override
public void onStop() {
super.onStop();
if(D) Log.e(TAG, "-- ON STOP --");
}
@Override
public void onDestroy() {
super.onDestroy();
if(D) Log.e(TAG, "--- ON DESTROY ---");
unregisterReceiver(CurveReceiver);
unbindService(CurveServiceConncetion);
}
public void doBind(){
Boolean tmp;
tmp = bindService(new Intent(this, Curve.class), CurveServiceConncetion, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE
IntentFilter filter = new IntentFilter(Curve.NEWCURVE_POINT);
registerReceiver(CurveReceiver, filter);
}
对我来说这个问题是因为 Curve.class 在初始 doBind() 之后再次调用其构造函数。 当然必须有办法解决这个问题,否则我必须使用 Curve.class 中的代码加载在层次结构中更接近 UI 的工作类???
编辑 Curve 是一个处理从外部机器发送的数据、常量等的对象,并将处理后的数据包含在数组中。 logCat 当然存在,我只是没有在正确的位置查找,它是
ARN/System.err(10505): java.lang.NullPointerException 警告/System.err(10505):位于 android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:271) 警告/System.err(10505):位于 pi.droid.Core.Curve.refreshintent(Curve.java:206) 警告/System.err(10505):位于 pi.droid.Core.Curve.AddPoint(Curve.java:400) 警告/System.err(10505):位于 pi.droid.Core.Comm.CommMeasure$CommMeasurement.AddPoint(CommMeasure.java:363) 警告/System.err(10505):位于 pi.droid.Core.Comm.CommMeasure$GenericCommMeasurement.TryProcessData(CommMeasure.java:168) 警告/System.err(10505):位于 pi.droid.Core.Comm.CommMeasure$CommMeasurement.ProcessData(CommMeasure.java:302) 警告/System.err(10505):at pi.droid.Core.Comm.ClientConnection$timer_tick.run(ClientConnection.java:164) WARN/System.err(10505): at java.util.Timer$TimerImpl.run(Timer.java:289)
您还可以看到我使用的其他 2 个工作类的链。 Curve 的构造函数在 CommMeasure 绑定后调用。 所以这是我的问题。 我是否需要完全改变我的程序的设置方式,或者有其他方法可以解决这个问题吗?
最终编辑 该代码来自 C#,Curve 使用事件处理程序来传递数据。我摆脱了所有它们(java监听器)并使用android Handler和broadcastreceiver。 有人建议我应该传递 CurveService,但这会出现问题,因为 Curve 有多个构造函数。服务没有参数 1,然后是像这样的 1,
public Curve(Unit XUnit, Unit YUnit)
{ this.Title = "Curve";
this.finished = false;
this.XUnit = XUnit;
this.YUnit = YUnit;
this.YDirection = CurveDirection.Unspecified;
}
所以实例化肯定会出现 CurveService 的问题,它必须是这样的: public Curve(){} ?? 无论如何,非常感谢您的所有帮助和建议。
最终编辑 +1..lol
UI 创建了一个新的 ClientConnection 实例,该实例又创建了一个新的 CommMeasure 实例,最后 CommMeasure 创建了一个新的 Curve 实例来访问 Curve.addpoint。 我认为这个线程和另一个链接的1超出了一个简单的android问题,并强调了代码移植的困难。例如,任何阅读本文的 .Net 开发人员都会比我更快地了解 Android 的一些特性。那里还有很好的工作代码。 感谢所有提供帮助的人,尤其是贾斯汀·布莱特菲勒 (Justin Breitfeller)
This is my second post today as fixing the 1st post lead to another problem which I am really struggling on. I want to use Broadcasts and intent to send data packets back from a service to the UI. I managed to bind and start the service successfully
see my other post if you want history and code
The null pointer exception comes on the sendBroadcast() inside the service. The service class does have its constructor re-called after binding the UI to the service. This happens from another class so Context can not be easily used. So I guess the sendBroadcast has no-where to go :(
I suspect this is my problem...the re-calling of the Service constructor after the initial binding. I have onDestroy, onPause and onResume covered with binding an unbinding.
Any ideas or suggestion would be great or maybe I am just going about this wrong is there another way?
EDIT
The previous problem of binding is now solved and due to me being new to the forums a slight delay in accepting the answer...sorry.
The class diagram is like this (it is ported C#code)
Activity doBind (on Curve.class)---> Activity starts a worker class (not treated as a service) Comm.class with a Handler for some comms--> the Comm starts another worker class --> previous worker class finally calls new Curve.class.
It is this last stage Curve.class where the sendBroadcastReceiver() then throws a nullpointer ref becasue the binder is lost.
I tested the broadcastreceiver just with a simple timer cutting out the worker classes in between and it works fine. Problems start when the Curve.class is recalled later further down the hierarchy and the binder gets nulled or "lost".
I removed all references of the binder from Curve except in onBind(). This might not be a good idea. Again the code below does work if used with a simple timer started directly from the UI (no other worker classes).
Some more code here:
The service
public class Curve extends Service
{
private NewCurvePointEventArgs newpoint = null;
private static final String TAG = "Curve";
Intent intent;
int counter = 0;
@Override
public void onCreate() {
super.onCreate();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
IBinder mBinder = new LocalBinder<Curve>(this);
return mBinder;
}
@Override
public void onStart(Intent intent, int startId) {
}
@Override
public void onDestroy() {
}
public Curve(){
}
private void refreshintent(NewCurvePointEventArgs tmp)
{
ArrayList<String> thepoint = new ArrayList<String>();
thepoint.add()//various things added here
Bundle bundle = new Bundle();
// add data to bundle
bundle.putStringArrayList("New_Point", thepoint);
intent = new Intent();
intent.setAction(NEWCURVE_POINT);
intent.putExtra("NEW_POINT", bundle
sendBroadcast(intent);
}
The activity has this code now. the doBind() is called after the onCreate of the activity.
private BroadcastReceiver CurveReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Curve.NEWCURVE_POINT)) {
displaynewpoint(intent);
}
}
};
private ServiceConnection CurveServiceConncetion = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
CurveService = ((LocalBinder<Curve>) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
CurveService = null;
}
};
@Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
}
@Override
public synchronized void onPause() {
super.onPause();
if(D) Log.e(TAG, "- ON PAUSE -");
}
@Override
public void onStop() {
super.onStop();
if(D) Log.e(TAG, "-- ON STOP --");
}
@Override
public void onDestroy() {
super.onDestroy();
if(D) Log.e(TAG, "--- ON DESTROY ---");
unregisterReceiver(CurveReceiver);
unbindService(CurveServiceConncetion);
}
public void doBind(){
Boolean tmp;
tmp = bindService(new Intent(this, Curve.class), CurveServiceConncetion, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE
IntentFilter filter = new IntentFilter(Curve.NEWCURVE_POINT);
registerReceiver(CurveReceiver, filter);
}
This problem to me is because the Curve.class has its constructor called again after the initial doBind().
Surely there must be a way around this otherwise I have to load my worker classes closer in hierarchy to the UI with the code from Curve.class???
EDIT
Curve is an object that processes data, constants etc sent from an external machine and contains the processed data in arrays.
The logCat did of course exist I just wasn't looking in the right place here it is
ARN/System.err(10505): java.lang.NullPointerException
WARN/System.err(10505): at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:271)
WARN/System.err(10505): at pi.droid.Core.Curve.refreshintent(Curve.java:206)
WARN/System.err(10505): at pi.droid.Core.Curve.AddPoint(Curve.java:400)
WARN/System.err(10505): at pi.droid.Core.Comm.CommMeasure$CommMeasurement.AddPoint(CommMeasure.java:363)
WARN/System.err(10505): at pi.droid.Core.Comm.CommMeasure$GenericCommMeasurement.TryProcessData(CommMeasure.java:168)
WARN/System.err(10505): at pi.droid.Core.Comm.CommMeasure$CommMeasurement.ProcessData(CommMeasure.java:302)
WARN/System.err(10505):at pi.droid.Core.Comm.ClientConnection$timer_tick.run(ClientConnection.java:164)
WARN/System.err(10505): at java.util.Timer$TimerImpl.run(Timer.java:289)
You can also see the chain of the 2 other worker classes I use. The constructor of Curve is called after the bind from CommMeasure.
So this is my problem.
Do I need to totally change how my program is set up or is there another way around this?
FINAL EDIT
This code is brought from c# and Curve used eventhandlers to pass data around. I got rid of all them(java listeners) and used android Handler and broadcastreceiver.
It has been suggested that I should pass the CurveService around but this will be problematic as Curve has multiple constructors. The no parameter 1 for the service and then 1 like this
public Curve(Unit XUnit, Unit YUnit)
{ this.Title = "Curve";
this.finished = false;
this.XUnit = XUnit;
this.YUnit = YUnit;
this.YDirection = CurveDirection.Unspecified;
}
so surely instantiating that would be a problem with CurveService, which has to be like this: public Curve(){} ??
Anyway many thanks for all your help and advice.
Final Edit +1..lol
The UI creates a new instance of ClientConnection, that in turns creates a new instance of CommMeasure and finally CommMeasure creates a new instance of Curve to access Curve.addpoint.
I think this thread and the other linked 1 goes beyond a simple android problem and highlights the difficulties of code porting. Any .Net developer for example reading this will learn some peculiarities of android a lot quicker than I did. There is also good working code in there.
Thanks to all who helped especially Justin Breitfeller
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最好的做法是遵循 Android APIDemos 中的示例。
像您想使用的那样使用服务:
http://developer.android .com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html
查看此文件内的 Binding 类,以查看执行绑定操作的类,如下所示:
http://developer.android .com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html
最后,如果您的构造函数在您的服务上被调用两次,则您不会绑定到您的服务正常,或者您可能意外地解除了它的绑定并再次绑定到它。
编辑
从堆栈跟踪来看,CommMeasure 似乎需要引用您在 onServiceConnected 中收到的 Curve 实例。
编辑2
如果您确实想让您的生活变得简单,请将 getApplicationContext() 传递给您的 CommMeasure 类,然后只需从该类中 appContext.sendBroadcast() 即可发送您的观点。这将防止您在长时间运行的任务中需要引用该服务。
The best thing for you to do is follow the example from the Android APIDemos.
A service to be used like you want to use it:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html
Look at the Binding class inside of this file to see a class that does binding like you should:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html
Finally, if your constructor is being called twice on your service, you aren't binding to your service properly, or perhaps you are unbinding from it and binding to it again unexpectedly.
EDIT
From the stack trace, it appears that CommMeasure needs to have a reference to the instance of Curve that you receive in onServiceConnected.
EDIT 2
If you really want to make your life simple, pass getApplicationContext() to your CommMeasure class and just appContext.sendBroadcast() from that class to send out your point. This will prevent you from requiring a reference to the service in your long-running task.