我正在开发一个Android聊天应用程序。我在app中有一个活动和服务。这里的服务包含所有连接功能,活动和服务之间的通信是使用binder完成的。我的服务在后台运行但是一段时间后我看到在模拟器中的设置菜单中看到了这个过程后,连接会自动关闭。我已经看到两个选项,两个克服这一点,首先是在一个单独的进程中运行服务,我现在试图避免。另一个是在一个单独的线程中运行连接,但我需要一个人来帮助我,因为我无法这样做。这是我的代码
public class MainService extends Service{
private XMPPConnection connection;
private final IBinder mBinder = new MyBinder();
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("service","started");
new Connect().execute("");
return START_STICKY;
}
private class Connect extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
ConnectionConfiguration connConfig = new ConnectionConfiguration(SERVICE,PORT);
XMPPConnection connection = new XMPPConnection(connConfig);
try {
connection.connect();
Log.i("XMPPChatDemoActivity",
"Connected to " + connection.getHost());
} catch (XMPPException ex) {
Log.e("XMPPChatDemoActivity", "Failed to connect to "
+ connection.getHost());
Log.e("XMPPChatDemoActivity", ex.toString());
setConnection(null);
}
try {
// SASLAuthentication.supportSASLMechanism("PLAIN", 0);
connection.login(USERNAME, PASSWORD);
Log.i("XMPPChatDemoActivity",
"Logged in as " + connection.getUser());
// Set the status to available
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
setConnection(connection);
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
Log.d("XMPPChatDemoActivity",
"--------------------------------------");
Log.d("XMPPChatDemoActivity", "RosterEntry " + entry);
Log.d("XMPPChatDemoActivity",
"User: " + entry.getUser());
Log.d("XMPPChatDemoActivity",
"Name: " + entry.getName());
Log.d("XMPPChatDemoActivity",
"Status: " + entry.getStatus());
Log.d("XMPPChatDemoActivity",
"Type: " + entry.getType());
Presence entryPresence = roster.getPresence(entry
.getUser());
Log.d("XMPPChatDemoActivity", "Presence Status: "
+ entryPresence.getStatus());
Log.d("XMPPChatDemoActivity", "Presence Type: "
+ entryPresence.getType());
Presence.Type type = entryPresence.getType();
if (type == Presence.Type.available)
Log.d("XMPPChatDemoActivity", "Presence AVIALABLE");
Log.d("XMPPChatDemoActivity", "Presence : "
+ entryPresence);
}
} catch (XMPPException ex) {
Log.e("XMPPChatDemoActivity", "Failed to log in as "
+ USERNAME);
Log.e("XMPPChatDemoActivity", ex.toString());
setConnection(null);
}
return null;
}}
public void setConnection(XMPPConnection connection) {
this.connection = connection;
if (connection != null) {
// Add a packet listener to get messages sent to us
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message
.getFrom());
Log.i("XMPPChatDemoActivity", "Text Recieved " + message.getBody()
+ " from " + fromName );
}
}
}, filter);
}
}
public class MyBinder extends Binder
{
MainService getService() {
return MainService.this;
}
}
public XMPPConnection getconnection()
{
if (connection != null) {
Log.d("MainService","connection send");
return connection;
}
else
{
Log.d("MainService","connection null");
return null;
}
} }
public class XMPPChatDemoActivity extends Activity {
private MainService service;
private XMPPConnection connection;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if(!isMyServiceRunning())
{
startService(new Intent(this,MainService.class));
}
}
@Override
protected void onResume() {
bindService(new Intent(this, MainService.class), mConnection,
Context.BIND_AUTO_CREATE);
super.onResume();
}
@Override
protected void onPause() {
unbindService(mConnection);
super.onPause();
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
service = ((MainService.MyBinder) binder).getService();
Log.d("Service","Connected");
Toast.makeText(XMPPChatDemoActivity.this, "Connected", Toast.LENGTH_SHORT)
.show();
connection=service.getconnection();
}
public void onServiceDisconnected(ComponentName className) {
connection=null;
service = null;
}
};
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MainService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
答案 0 :(得分:0)
你们两个提到看似解决方案都没有解决问题:Android在资源不足时会终止服务。通常,您可以通过
解决此问题将服务标记为前景(在这种情况下不推荐 1 )
将服务标记为STICKY
,以便在服务被杀后重新启动
我真的建议使用STICKY
方法。运行具有前台活动的服务,au更简单,因为您只需添加一行额外代码,但它也会阻止Android释放其他地方迫切需要的资源。如果您的服务作为前台运行并且遭受形式内存泄漏或由于某些其他原因导致内存使用率过高,则设备将变慢并且Android无法解决此问题。
因此,最好的方法是将服务标记为STICKY
,并在重新启动后恢复其状态。所有优秀的Android XMPP客户都可以做到这一点。
1:前台服务旨在用于重启会导致糟糕用户体验的服务,例如:如果音乐播放器服务重新启动,用户将注意到它。这是将服务标记为前景的典型示例。