2

バックグラウンドで Xmpp サーバーにアクセスするプロジェクトを開始しています。接続を維持し、必要に応じて再接続します + 他の Xmpp 処理を行います。

仕事をするためのクラスを実装したい。Servicesクラスは、他の( Location...) およびBroadcastReceivers(CONNECTIVITY_CHANGE ....)と対話する必要があります。基本的に、アクティビティとブロードキャスト レシーバーは、Xmpp クラスに、接続、切断、再接続、チャットへの参加、メッセージの送信などのアクションの開始を要求します。

最初のアプローチは、として実装することですServiceが、サービスはメインスレッドで実行されるため、実装は間違っています。

第二に、非同期で実行され、メインスレッドから外れているIntentServiceため、それを として作成したかったのです。onHandleIntent

ただし、onHandleIntent非同期タスクを実行するために一度だけ実行されます。そのため、別の「アクション」を実行したい場合はActivity、ブロードキャスト イベントしか送信できず、再びメイン スレッドの問題に陥ります。また、IntentService常に「ライブ」であることを実際に目指しているわけではありません。

AsyncTaskGoogle のドキュメントでは、ネットワーク アクセスごとに実行する必要があると書かれています...これがネットワーク アクセスを行う唯一の方法ですか...これはかなり悲しいことです。

GTalkSMS の実装を調べたところ、同じ問題があるようでした。実際、彼らは次のような管理で を使用しServiceています。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 の Web サイトでは、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 に答える