سؤال

I am developing a android chat app.I have an activity and a service in the app.Here the service contains all the connection function and the communication between the activity and service is done using a binder.My service is running in background but the connection gets closed automatically when the process is finished after some time i see that in setting menu in the emulator.I have seen two options two overcome this first is to run service in a separate process which i am trying to avoid for now.Another is to run connection in a separate thread but i need some one to help me here as i am unable to do so.Here is my code

Service.java

    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;    
}

} }

Main Activity

    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;
}

}

هل كانت مفيدة؟

المحلول

Both of you mentioned seemingly solution don't approach the issue: Android kills services when its resources are getting low. Typically you can fix this by either

  1. Marking the service as foreground (In this case not recommended1)

  2. Marking the service as STICKY so that it get's restarted after it got killed

I really recommend using the STICKY approach. Running a service with foreground activity ,au be simpler, because you simply have to add only one line of extra code, but it also prevents Android from releasing resources that are urgently needed somewhere else. If you service runs as foreground and suffers form memory-leaks or has for some other reason high memory usage, the device will become slow and Android is unable to fix this situation.

Therefore the best approach is to mark your service as STICKY and restore it's state once it got restarted. All good Android XMPP clients do that.

1: Foreground services are intended for services where a restart would result in a bad user experience, e.g. if the music player service gets restarted, the user will notice it. That's the typical example where marking a service as foreground is appropriate.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top