2

我正在启动一个将在后台访问 Xmpp 服务器的项目。它将保持连接活动并在需要时重新连接+做其他 Xmpp 事情。

我想实现一个类来完成这项工作。该类必须与其他ServicesLocation...)和BroadcastReceivers(CONNECTIVITY_CHANGE ....)交互。基本上,Activity 和 Broadcast 接收器会要求 Xmpp 类启动一个动作,例如:CONNECT、DISCONNECT、RECONNECT、JOIN CHAT、SEND MESSAGE 等。

第一种方法是将其实现为Service但服务在主线程中运行,因此实现是错误的。

其次,我想把它做成一个,IntentService因为它onHandleIntent是异步运行的,然后我就退出了主线程。

但是onHandleIntent它只运行一次来​​执行异步任务。所以,如果我想Activity执行另一个“动作”,我只能发送一个广播事件,我将再次陷入主线程问题。此外,IntentService它的目标并不是一直“活着”。

在谷歌文档中,他们说你需要AsyncTask为每个网络访问运行......这是进行网络访问的唯一方法......这很可悲。

我查看了 GTalkSMS 中的实现,他们似乎也有同样的问题。实际上,他们使用 aService和这样的ServiceHandler管理:

// some stuff for the async service implementation - borrowed heavily from
// the standard IntentService, but that class doesn't offer fine enough
// control for "foreground" services.
private static volatile Looper sServiceLooper;
private static volatile ServiceHandler sServiceHandler;

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent) msg.obj, msg.arg1);
    }
}
4

1 回答 1

1

好吧,似乎唯一的方法是创建一个拥有自己线程的服务。

Vogella 网站描述了一种在 AndroidManifest 中设置服务的方法:
“4. 单独进程中的服务”

<service
  android:name="WordService"
  android:process=":my_process" 
  android:icon="@drawable/icon"
  android:label="@string/service_name"
  >
</service> 

另一种方法是手动执行服务处理程序,正如我在最初的帖子中所描述的那样:

public class XmppService extends Service {

    public final static String ACTION_CONNECT = "action.CONNECT";
    public final static String ACTION_DISCONNECT = "action.DISCONNECT";

    // some stuff for the async service implementation - borrowed heavily from
    // the standard IntentService, but that class doesn't offer fine enough
    // control for "foreground" services.
    private static volatile Looper sServiceLooper;
    private static volatile ServiceHandler sServiceHandler;
    private long mHandlerThreadId;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(android.os.Message msg) {
            onHandleIntent((Intent) msg.obj, msg.arg1);
        }
    }

    /**
     * The IntentService(-like) implementation manages taking the intents passed
     * to startService and delivering them to this function which runs in its
     * own thread 
     *
     * @param intent
     * @param id
     */
    void onHandleIntent(final Intent intent, int id) {
        // ensure XMPP manager is setup (but not yet connected)
        if (Thread.currentThread().getId() != mHandlerThreadId) {
            throw new IllegalThreadStateException();
        }

        String action = intent.getAction();
        if(action.equals(XmppService.ACTION_CONNECT)){
            // Do Connect
        }
        else if(action.equals(XmppService.ACTION_DISCONNECT)){
            // Do Disconnect
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // Start a new thread for the service
        HandlerThread thread = new HandlerThread(SERVICE_THREAD_NAME);
        thread.start();
        mHandlerThreadId = thread.getId();
        sServiceLooper = thread.getLooper();
        sServiceHandler = new ServiceHandler(sServiceLooper);

    }
}
于 2013-11-14T23:59:38.190 回答