2013-07-18 3 views
0

Мое приложение отправляет данные на сервер. Обычно он работает нормально, пока пользователь не окажется в зоне плохого сигнала. Если пользователь находится в зоне хорошего сигнала, следующий код работает нормально и данные отправляются.AsyncTask.get() no progress bar

String[] params = new String[]{compID, tagId, tagClientId, carerID, 
       formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
     AsyncPostData apd = new AsyncPostData(); 

      apd.execute(params); 

.

private class AsyncPostData extends AsyncTask<String, Void, String> { 

     ProgressDialog progressDialog; 
     String dateTimeScanned; 

     @Override 
     protected void onPreExecute() 
     { 


      // progressDialog= ProgressDialog.show(NfcscannerActivity.this, 
       // "Connecting to Server"," Posting data...", true); 

      int buildVersionSdk = Build.VERSION.SDK_INT; 
      int buildVersionCodes = Build.VERSION_CODES.GINGERBREAD; 

      Log.e(TAG, "buildVersionSdk = " + buildVersionSdk 
        + "buildVersionCodes = " + buildVersionCodes); 

      int themeVersion; 
      if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD) { 

       themeVersion = 2; 

      }else{ 

       themeVersion = 1; 
      } 

      progressDialog = new ProgressDialog(NfcscannerActivity.this, themeVersion); 
      progressDialog.setTitle("Connecting to Server"); 
      progressDialog.setMessage(" Sending data to server..."); 
      progressDialog.setIndeterminate(true); 

      try{ 
      progressDialog.show(); 
      }catch(Exception e){ 

       //ignore 
      } 
     }; 


     @Override 
     protected String doInBackground(String... params) { 

      Log.e(TAG, "carerid in doinbackground = " + params[3] + " dateTimeScanned in AsyncPost for the duplecate TX = " + params[4]); 

      dateTimeScanned = params[4]; 

      return nfcscannerapplication.loginWebservice.postData(params[0], params[1], params[2], params[3], params[4], 
        params[5], params[6], params[7] + getVersionName(), params[8], params[9]); 

     } 

     @Override 
      protected void onPostExecute(String result) 
      { 
      super.onPostExecute(result); 

       try{ 
       progressDialog.dismiss(); 
       }catch(Exception e){ 
        //ignore 
       } 

       if(result != null && result.trim().equalsIgnoreCase("OK") ){ 

        Log.e(TAG, "about to update DB with servertime"); 
        DateTime sentToServerAt = new DateTime(); 
        nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerAt,null); 
        nfcscannerapplication.loginValidate.insertIntoDuplicateTransactions(dateTimeScanned); 

        tagId = null; 
        tagType = null; 
        tagClientId = null; 

        //called to refresh the unsent transactions textview 
        onResume(); 

       }else if(result != null && result.trim().equalsIgnoreCase("Error: TX duplicated")){ 
        Log.e(TAG, "response from server is Duplicate Transaction "); 


        //NB. the following time may not correspond exactly with the time on the server 
        //because this TX has already been processed but the 'OK' never reached the phone, 
        //so we are just going to update the phone's DB with the DupTX time so the phone doesn't keep 
        //sending it. 

        DateTime sentToServerTimeWhenDupTX = new DateTime(); 
        nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerTimeWhenDupTX,null); 

        tagId = null; 
        tagType = null; 
        tagClientId = null; 



       }else{ 

        Toast.makeText(NfcscannerActivity.this, 
          "No phone signal or server problem", 
          Toast.LENGTH_LONG).show(); 
       } 
      } 

    }//end of AsyncPostData 

.

Приложение в зонах с плохим сигналом имеет тенденцию отображать индикатор выполнения в течение нескольких минут, прежде чем отображать черный экран в течение некоторого времени, делая приложение непригодным.

Я думал, что это будет сделано для следующего.

String[] params = new String[]{compID, tagId, tagClientId, carerID, 
       formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
     AsyncPostData apd = new AsyncPostData(); 
     try { 
      apd.execute(params).get(10, TimeUnit.SECONDS); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (TimeoutException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

Это заставит AsyncTask отменить через 10 секунд, но, как он выполняется там черный экран, пока данные не передаются последующим ProgressBar в течение нескольких миллисекунд.

Есть ли способ показать прогрессную панель при выполнении AsyncTask.get()?

благодарит заранее. матовый.

Также есть идеи, почему черный экран появляется, когда пользователь находится в зоне плохого сигнала и от этого не реагирует на сервер. Этот сенарио, похоже, вызывает множество проблем, когда это поведение необычно после этого, как отправка дополнительных транзакций позднее.

[edit1]

public class SignalService extends Service{ 

    NfcScannerApplication nfcScannerApplication; 
    TelephonyManager SignalManager; 
    PhoneStateListener signalListener; 
    private static final int LISTEN_NONE = 0; 
    private static final String TAG = SignalService.class.getSimpleName(); 


    @Override 
    public void onCreate() { 
     super.onCreate(); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService created"); 
     nfcScannerApplication = (NfcScannerApplication) getApplication(); 
     signalListener = new PhoneStateListener() { 
      public void onSignalStrengthChanged(int asu) { 
       //Log.e("onSignalStrengthChanged: " , "Signal strength = "+ asu); 
       nfcScannerApplication.setSignalStrength(asu); 

      } 
     }; 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService destroyed"); 
     SignalManager.listen(signalListener, LISTEN_NONE); 

    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService in onStart"); 

     SignalManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
     SignalManager.listen(signalListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTH); 

    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 
+0

Использование 'get()' только ухудшит UX: [Черный экран во время работы AsyncTask] (http://stackoverflow.com/a/15259698/2558882). – Vikram

+0

mmm да, я знаю, что он блокирует поток пользовательского интерфейса, но я не знаю, как я могу установить таймер на асинтезу, чтобы отменить, не используя .get(). – turtleboy

+0

Можно ли отменить asynctask с помощью обработчика? – turtleboy

ответ

0

Вам не нужно таймер на все, чтобы делать то, что вы пытаетесь (по какой-то причине, я думал, что вы пытались автоматического повтора AsyncTask на основе ваших комментариев, выше которого в результате мой.). Если я правильно понимаю, вы проблема с потерей обслуживания. У вас есть AsyncTask, который вы начинаете, который может или не может закончиться в зависимости от определенных условий. Ваш подход состоял в том, чтобы использовать get и cancle задачу после определенного времени в случае, если она не закончила выполнение до этого - предположение, что если задача не завершилась в течение 10 секунд, служба была потеряна.

Лучшим способом решения этой проблемы является использование логического флага, который указывает, доступна ли сетевая связь, а затем прекратить выполнение задачи, если служба потеряна. Вот пример, который я взял из this post (извиняюсь за форматирование, которое я на дерьмовом компьютере, - из всех вещей - IE8 - поэтому я не вижу, как выглядит код).

public class MyTask extends AsyncTask<Void, Void, Void> { 

private volatile boolean running = true; 
private final ProgressDialog progressDialog; 

public MyTask(Context ctx) { 
    progressDialog = gimmeOne(ctx); 

    progressDialog.setCancelable(true); 
    progressDialog.setOnCancelListener(new OnCancelListener() { 
     @Override 
     public void onCancel(DialogInterface dialog) { 
      // actually could set running = false; right here, but I'll 
      // stick to contract. 
      cancel(true); 
     } 
    }); 

} 

@Override 
protected void onPreExecute() { 
    progressDialog.show(); 
} 

@Override 
protected void onCancelled() { 
    running = false; 
} 

@Override 
protected Void doInBackground(Void... params) { 

    while (running) { 
     // does the hard work 
    } 
    return null; 
} 

// ... 

} 

В этом примере используется диалоговое окно прогресса, позволяющее пользователю выполнить задачу, нажав кнопку. Вы не собираетесь это делать, а скорее собираетесь проверить сетевую связность и установить текущее логическое значение в зависимости от того, связана ли ваша задача с Интернетом. Если соединение потеряно - запуск будет установлен на false, который отключит цикл while и остановит задачу.

Что касается работы после завершения задачи. Вы никогда не должны использовать get. Либо (1) поместить все, что нужно сделать после doInBackgroundCompletes в onPostExecute (при условии, что оно не слишком много) или (2), если вам нужно вернуть данные в начальную активность, используя интерфейс. Вы можете добавить интерфейс, добавив в качестве аргумента в свой конструктор задач или используя отдельный метод, который устанавливает интерфейс вверх.Например

public void setInterface(OnTaskComplete listener){ 
    this.listener = listener; 
} 

Где OnTaskComplete слушатель объявляется как переменная экземпляра в вашем AsyncTask. Обратите внимание, что подход, который я описываю, требует использования отдельного класса AsyncTask. Теперь вы являетесь частным лицом, что означает, что вам нужно немного изменить свой проект.

UPDATE

Для проверки соединения я хотел бы использовать что-то вроде этого.

public boolean isNetworkOnline() { 
boolean status=false; 
try{ 
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo netInfo = cm.getNetworkInfo(0); 
    if (netInfo != null && netInfo.getState()==NetworkInfo.State.CONNECTED) { 
     status= true; 
    }else { 
     netInfo = cm.getNetworkInfo(1); 
     if(netInfo!=null && netInfo.getState()==NetworkInfo.State.CONNECTED) 
      status= true; 
    } 
}catch(Exception e){ 
    e.printStackTrace(); 
    return false; 
} 
return status; 

} 

Вы можете проверить, есть ли фактическое сетевое соединение, по которому ваше приложение может подключиться к серверу. Этот метод не обязательно должен быть общедоступным и может быть частью вашего класса AsyncTask. Лично я использую что-то похожее на это в классе сетевого менеджера, который я использую для проверки различной сетевой статистики (одним из которых я могу подключиться к Интернету).

Вы должны проверить подключение до того, как вы начнете выполнять цикл в методе doInBackground, а затем вы можете периодически обновлять его на протяжении всего курса. Если netowkr будет доступен, задача будет продолжена. Если нет, это остановится.

Вызов AsyncTask встроенный метод cancle не является достаточным, потому что это только предотвращает onPostExecute от работы. Это фактически не останавливает выполнение кода.

+0

Приветствую вас за ваш вклад. Я понимаю, что вы имеете в виду, но можете ли вы более подробно рассказать о проверке подключения к сети. Я написал код, который проверяет уровень сигнала, но я иногда обнаружил его ненадежным (всегда говорящий без сигнала, когда есть). Я опубликовал редактирование с кодом сигнала, это по правильным строкам? благодаря – turtleboy