java - Not able to connect with a Service
问题描述
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!
解决方案
调用bindService()
返回一个布尔结果,告诉您绑定是否成功(实际上,这意味着正在进行中)。该操作是异步的,即使在同一个进程中(这就是你LocalBinder
的。)
换句话说,在你ServiceConnection.onServiceConnected()
被回调之前,绑定是不完整的。一旦该回调被触发并且您获得了服务绑定器,您就可以调用支持服务。
其他一些可以帮助您的注意事项:
- 由于您
Service
与您在同一进程中运行Activity
,因此调用是直接的并且不使用活页夹线程。这将对您的Activity
代码产生影响。 - 阻塞调用不应该是主 (UI) 线程上的主线程。这意味着如果您的
Activity
代码要调用socketService.connect()
,则需要从后台线程执行此操作。否则,您将收到异常,因为 Android 现在会阻止主线程上的网络 I/O。其他类型的阻塞操作可能会导致 ANR,这将导致您的应用程序崩溃。 - 如果您的网络 I/O 用于 REST 或其他与 HTTP 相关的流量,请考虑使用 Retrofit 或 Volley,因为它们具有高性能、可扩展性,并且可以为您处理与网络和 HTTP 相关的繁重工作。
推荐阅读
- java - 转换一个 java 列表
进入可与 iomicrometer 的 MultiGauge 一起使用的流 - python-3.x - 如何遍历嵌套字典并检查列表中是否存在键
- javascript - 我需要正则表达式来屏蔽 javascript 中的电子邮件地址
- anylogic - 如何在任何逻辑中从源头停止到达率?
- business-process-management - BPM公式应该解释一下
- javascript - 如何通过单击按钮更改选中的下一个单选按钮?
- linux - PhpStorm 每次都会询问 GitHub 的用户名和密码
- html - 我的下拉菜单在导航栏中不起作用
- xcode - 无法将“String”类型的值分配给“UILabel”类型?
- android - Android长按系统后退键监听