I have a background service that is started on BOOT COMPLETE with a broadcast receiver.
what I wanted to do is to create another application that will bind to that service using AIDL interface.
the app simply asks the user to enter ip number and port , and when he clicks the button the service should receive these data. my problem is that when I enter the data and click "submit" the app crashes with a nullPointerException. and when I debug the app I see that the OnServiceConnected isn't being called at all.
I think I defined the AIDL files well, I can't figure out what's wrong here.
the AIDL file (aidl is within the same package name at the service and at the client) :
interface ISetIpPort{
void getIpPort(String ip,int port);
}
My service (the relevant methods) :
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return (new IpPortBinder(getApplicationContext()));
}
private static class IpPortBinder extends ISetIpPort.Stub{
Context context;
public IpPortBinder(Context context) {
this.context=context;
}
@Override
public void getIpPort(String ip, int port) throws RemoteException {
Toast.makeText(context, "Received ip " +ip+" And port "+port, Toast.LENGTH_LONG);
}
}
My application :
public class MainActivity extends Activity implements OnClickListener,ServiceConnection {
private Button submitButton,cancelButton;
private EditText ipText,portText;
private ISetIpPort binding=null;
String ip;
String port;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
submitButton=(Button) findViewById(R.id.okButton);
submitButton.setOnClickListener(this);
cancelButton=(Button) findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(this);
ipText=(EditText) findViewById(R.id.ip);
portText=(EditText) findViewById(R.id.port);
}
@Override
public void onClick(View v) {
if(v==findViewById(R.id.okButton)){
ip=ipText.getText().toString();
port=portText.getText().toString();
int portInteger=Integer.parseInt(port);
try {
binding.getIpPort(ip, portInteger);
} catch (RemoteException e) {
// TODO Auto-generated catch block
Log.e(getClass().getSimpleName(),"Exception requesting to set ip and port",e);
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
if(v==findViewById(R.id.cancelButton)){
finish();
System.exit(0);
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Intent implicit=new Intent(ISetIpPort.class.getName());
List<ResolveInfo> matches=getPackageManager().queryIntentServices(implicit, 0);
if(matches.size()==0){
Toast.makeText(getApplicationContext(), "Cannot find a matching service!", Toast.LENGTH_LONG).show();
}
else if (matches.size()>1){
Toast.makeText(getApplicationContext(), "Found multiple matching services!", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(getApplicationContext(), "service attached!", Toast.LENGTH_LONG).show();
Intent explicit=new Intent(implicit);
ServiceInfo svcInfo=matches.get(0).serviceInfo;
ComponentName cn=new ComponentName(svcInfo.applicationInfo.packageName, svcInfo.name);
explicit.setComponent(cn);
bindService(explicit, this, Context.BIND_WAIVE_PRIORITY);
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binding=ISetIpPort.Stub.asInterface(service);
submitButton.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name) {
binding=null;
submitButton.setEnabled(false);
}
}
Don't worry about me not validating ip or port insertion. I just want to first test this IPC .