Reputation: 3
I'm trying to create a service that handles networking in my app. I followed all the steps in https://developer.android.com/reference/android/app/Service and https://developer.android.com/guide/components/bound-services#Binding, but the activity doesn't seem to connect with the service.
Here is the SocketService, which has the TcpClient object that connects to my server using sockets:
public class SocketService extends Service{
TcpClient tcpClient = new TcpClient();
private final IBinder mBinder = new LocalBinder();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
SocketService getService() {
// Return this instance of LocalService so clients can call public methods
return SocketService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/*
* Client methods
*/
public void connect(MyCallback callback, String ip, int port){
tcpClient.connect(callback, ip, port);
}
public String disconnect(){
return tcpClient.disconnect();
}
public String send(String data){
return tcpClient.send(data);
}
public String recv(){
return tcpClient.recv();
}
}
Here is my main activity:
public class MainActivity extends AppCompatActivity {
SocketService socketService;
boolean bound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart(){
super.onStart();
Intent serviceIntent = new Intent(MainActivity.this, SocketService.class);
if(bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)){
Toast.makeText(getApplicationContext(), "bound", Toast.LENGTH_LONG);
}
if(bound) {
socketService.connect(this, ip, port);
} else {
Toast.makeText(getApplicationContext(), "not bond", Toast.LENGTH_LONG).show();
}
}
/*
* Service callback
*/
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
Toast.makeText(getApplicationContext(), "ServiceConnection", Toast.LENGTH_LONG);
socketService = ((SocketService.LocalBinder) service).getService();
bound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
socketService = null;
bound = false;
}
};
}
And the AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.drrbarrera.home">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".SocketService"
android:enabled="true"
android:exported="true">
</service>
</application>
</manifest>
As I said before, the MainActivity doesn't seem to connect. "socketService" (in the MainActivity) stays null and "bound" stays false, like if "mConnection" wasn't being executed. Any idea of what might be wrong? Any help is appreciated. Thanks in advance!
Upvotes: 0
Views: 54
Reputation: 15775
The call to bindService()
returns a boolean result telling you whether the bind is successful (really, it means in progress). The operation is asynchronous, even within the same process (which is what your LocalBinder
is.)
In other words, the binding is not complete until your ServiceConnection.onServiceConnected()
is called back. Once that callback is hit and you get the service binder, then you can call through to the backing service.
A few other notes to help you out:
Service
is running in the same process as your Activity
, the calls are direct and not using binder threads. This will have an effect on your Activity
code.Activity
code is going to call socketService.connect()
, it will need to do it from a background thread. Otherwise, you will get an exception as Android now prevents network I/O on the main thread. Other types of blocking operations can result in an ANR, which will result in your app crashing.Upvotes: 1