1

SOAP Web サービス呼び出しを送信するために使用しているサービスがあります。すべてが完璧に機能しており、クラッシュすることはありませんが、そうすべきだと思います。

私の問題は、クエリを長時間実行している場合 (10 ~ 50 秒)、ワーカースレッドが完了する前に onDestroy() が呼び出されることです (そして、stopSelfResult を呼び出します)。LogCat ウィンドウで System.out.println がすぐに実行されないか、同期が取れていない (キャッシュされている) 可能性がありますか?

QueryBase クラスを介してサービスを開始する方法は次のとおりです。

QueryBase someService  = new QueryBase(myActivity);
someService.execute(...);

私のQueryBaseクラス

public class QueryBase {

private WeakReference<Activity> currentActivity = null;

private static class ResponseHandler extends Handler {
    private QueryBase mQueryBase;

    public ResponseHandler(QueryBase vQueryBase) {
        mQueryBase = vQueryBase;
    };

    public void handleMessage(Message message) {
        Bundle extras = message.getData();

        mQueryBase.handleResult(message.arg1,message.arg2,extras.getInt("FRAMEID"),extras.getString("RESPONSE"));
        mQueryBase=null;
    };
};

public QueryBase(Activity vActivity) {
    currentActivity = new WeakReference<Activity>(vActivity);
}

/***************************************************************************
 * Start the service
 **************************************************************************/
public boolean execute(Activity vActivity, int cmdID, int frameID, String serverAddress, int requestType, String request) {

    // Valid activity
    if (vActivity==null) return false;

    // Test to see if network is connected
    if (!isOnline(vActivity)) return false;

    Intent webService                           = new Intent(vActivity, WebService.class);
    final ResponseHandler responseHD        = new ResponseHandler(this);
    Messenger messenger                     = new Messenger(responseHD);

    webService.putExtra("QUERYRESULT_MESSENGER",messenger);
    webService.putExtra("CMDID", cmdID);
    webService.putExtra("FRAMEID",frameID);
    webService.putExtra("SERVER_ADDRESS",serverAddress);
    webService.putExtra("REQUEST_TYPE",requestType);
    webService.putExtra("REQUEST",request);

    vActivity.startService(webService);     

    return true;
}

/***************************************************************************
 * Is my Android connected?
 **************************************************************************/
private Boolean isOnline(Activity vActivity) {
    ConnectivityManager connMgr = (ConnectivityManager) vActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) return true;
    else return false;
}

/***************************************************************************
 * Get current Activity
 **************************************************************************/
public Activity getCurrentActivity() {
    Activity ac = currentActivity.get();
    if (ac!=null) {
        if ((ac.isFinishing()) || (ac.activityDestroyed)) {
            return null;
        };
    }
    return ac;
};

/***************************************************************************
 * XML result from webservice
 **************************************************************************/
public void handleResult(int resultCode, int cmdID, int frameID, String response) {
    System.out.println("DEFAULT HANDLER: ResultCode: " + resultCode);
};

}

私の WebService クラス

public class WebService extends Service {

public static final int WS_RT_BLOOSOAP  = 0;
public static final int WS_RT_RSS       = 1;

public static final int WS_RESULT_OK = 0;
public static final int WS_RESULT_UNABLE_TO_CONNECT = 2;
public static final int WS_RESULT_INVALID_REQUEST = 3;
public static final int WS_RESULT_UNKNOWN_ERROR = 999;

static private SparseBooleanArray workList=null;        // Only one job with the same frameID is allowed to run

@Override
public void onCreate() {
    System.out.println("#### WebService onCreate");
    if (workList==null) workList = new SparseBooleanArray();
}

@Override
public void onDestroy() {
    System.out.println("#### WebService onDestroy");
}

/***************************************************************************
 * Start working
 **************************************************************************/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    System.out.println("WebService Start ID=" + startId);

    final int currentID         = startId;
    final Intent currentIntent = intent;

    Runnable workerRunnable = new Runnable() {
        public void run() {
            System.out.println("WebService Thread Start - ID=" + currentID);

            int resultCode;

            Bundle responseExtras = new Bundle();

            resultCode = serverRequest(currentIntent,responseExtras);
            sendResponse(currentIntent,resultCode,responseExtras);

            System.out.println("WebService Thread End - ID=" + currentID);

            Bundle  extras = currentIntent.getExtras();
            if (extras != null) {
                int frameID = extras.getInt("FRAMEID");             
                System.out.println(">>>>>>> PUT FALSE " + frameID);                 
                workList.put(frameID, false);
            };

            stopSelfResult(currentID);
        }
    };

    if (intent!=null) {
        Bundle  extras = intent.getExtras();

        if (extras != null) {
            int frameID = extras.getInt("FRAMEID");

            Boolean found = workList.get(frameID,false);
            if (!found) {
                System.out.println(">>>>>>> PUT TRUE FRAMEID=" + frameID);                  
                workList.put(frameID, true);

                Thread workerThread = new Thread(workerRunnable);
                workerThread.start();
            } else {
                System.out.println(">>>>>>> Allready running FRAMEID=" + frameID);                  
            }
        };
    };

    return Service.START_STICKY;
};

/***************************************************************************
 * No binding
 **************************************************************************/
@Override
public IBinder onBind(Intent intent) {
    return null;
}

/***************************************************************************
 * Send webservice request and return result in responseExtras
 **************************************************************************/
private int serverRequest(Intent intent, Bundle responseExtras) {
  ...
};

/***************************************************************************
 * Send response back to service caller using Messenger.send()
 **************************************************************************/
private boolean sendResponse(Intent intent, int resultCode, Bundle responseExtras) {
  ...
};
4

2 に答える 2

0

stopSelfResult()最新の で呼び出すと、サービスが停止しますstartId。そのため、サービスが startId=1 のインテントと startId=2 の別のインテントで開始され、2 番目のインテントが最初のインテントより前に終了した場合、startId=1 のインテントが終了する前に呼び出しstopSelfResult(2)ます。stopSelfResult()最新の startId で呼び出し、他のインテントが保留されていない場合、サービスはすぐに破棄されます。

最新の startId を保持します。処理したいすべての startIds を配列 (例: List<Integer> runningStartIds) に追加し、処理が終了したら削除します。終了時に削除した後、現在の startId を最新のものと比較し、 runningStartIds が空でない場合は呼び出しませstopSelfResult()stopSelfResult()そのため、すべてのインテントが処理され、保留中のインテントがなくなったときに、最新の startId のみを呼び出すことになります。

例を投稿していませんが、うまくいくはずです。

。:編集:。説明:バックグラウンドで何をしているかに関係なく、次Intentは戻ってくるのと同じくらい速く来るかもしれません。onStartCommand()

。:編集:。改善ではありません(改善:それについて考えると、実際には を保持するだけで済みます。完成した startId が一致するまでmLastStartId呼び出しをスキップしてください。stopSelfResult()mLastStartId

于 2013-08-21T14:32:11.040 に答える
0

残念ながら、それは常に起こる可能性があります。実際、Android アプリケーション コンポーネントのライフ サイクルは、デフォルトではどのタイプのワーカー スレッドとも同期されません。

そのため、サービスのステータスを手動で確認する必要がある場合があります。たとえば、サービスが機能しているかどうかを示すブール値フラグを 1 つ持つことができます。もう 1 つの便利な方法は、通常のサービスを使用する代わりにIntentServiceを使用することです。これは、ワーカー スレッドとライフサイクル機能を単独で処理します。

public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService ");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        // This callback-method is called inside worker thread, 
        // so you can do some long-time network job here.
        SystemClock.sleep(30000); // 30 seconds
        // In this timing the service will be stopped automatically.
    }
}    
于 2013-08-21T08:13:53.200 に答える