我正在处理的Android应用程序,与"服务器"在与我的应用程序相同的设备上运行。
由于我需要不断收听此服务器,因此我决定将其作为绑定服务。我查看了官方Android文档 here 以及一个很好的示例 here 。
当我在开发平板电脑上运行它们时,这两个例子都运行得很好。但是,当我尝试将这些示例合并到我自己的应用程序中时,它似乎无法正常工作。
这是我的 MainActivity.java :
public class MainActivity extends AppCompatActivity {
Listener myListener;
boolean isBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, Listener.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
myListener.listenToServer();
Toast.makeText(this, Integer.toString(myListener.getPort()), Toast.LENGTH_LONG).show();
}
@Override
protected void onStop() {
super.onStop();
if(isBound){
unbindService(serviceConnection);
isBound = false;
}
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Listener.LocalBinder localBinder = (Listener.LocalBinder) service;
myListener = localBinder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};
}
这是我的绑定服务, Listener.java :
public class Listener extends Service {
private boolean keepWorking = true;
private int localPort;
private final IBinder iBinder = new LocalBinder();
public class LocalBinder extends Binder {
Listener getService(){
return Listener.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
public void listenToServer(){
try {
byte[] buffer = new byte[16 * 1024];
DatagramPacket recvPacket = new DatagramPacket(buffer, buffer.length);
DatagramSocket server = new DatagramSocket(0);
server.setSoTimeout(1000);
localPort = server.getLocalPort();
while (keepWorking) {
try {
server.receive(recvPacket);
byte[] data = new byte[recvPacket.getLength()];
System.arraycopy(recvPacket.getData(), 0, data, 0, data.length);
} catch ( IOException ioe) {
// something here
}
}
} catch (SocketException se) {
// something here
}
}
public int getPort() {
return this.localPort;
}
public void stopWorking() {
this.keepWorking = false;
}
}
每当我尝试运行我的应用时,都会收到以下错误:
引起:java.lang.NullPointerException:尝试调用虚方法' Listener.listenToServer()'在空对象引用上
在MainActivity.onStart(MainActivity.java:19)
哪一行是myListener.listenToServer();
。
我知道我可以使用线程来实现这一点(因为我已经完成了它),但这需要一种不那么优雅的方法。我喜欢绑定的服务路线,因为我可以在我的应用程序的UI中轻松使用来自服务器的数据。
那么,发生了什么?我做错了什么?
由于
答案 0 :(得分:1)
问题是onServiceConnected()
回调不会同步调用。您只是要求系统为您绑定服务,这不会立即/同步发生。一旦发生绑定,您将收到onServiceConnected()
回调通知。因此,在bindService(...)
行之后,您的myListener
尚未初始化。
在myListener.listenToServer()
回调中执行onServiceConnected()
:
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Listener.LocalBinder localBinder = (Listener.LocalBinder) service;
myListener = localBinder.getService();
myListener.listenToServer();
isBound = true;
}