Где вставить код Android для связи с сервером через http

Вопрос состоит в том, как связаться с сервером Android с сервером, чтобы, если действие было оставлено, а вызов в действии не повторил транзакцию автоматически. Просто сейчас я использую AsyncTask Android для связи с сервером:

new AsyncTask<String, Void, List<String>>() {

    @Override
    protected void onPreExecute(
       showWaitDialog();        
    }

    @Override
    protected void onPostExecute(List<String> msgList) {
       //here I put the handling after the POST ie. error and success handling
       hideWaitDialog();

       if (msgList.isEmpty() {
          //success handling --> starting an new Activity
       } else {
          errorView.setText (...);
          errorLayout.setVisibility (View.VISIBLE); 
       }
    } 

    @Override
    protected List<String> doInBackground(String... params) {
       List<String> msgs = new ArrayList<String>();
       try{
          //for example submitting an JSONObject
          JSONObject result = HttpUtils.sendHttpPost(
              AppConstants.WEB_URL, jsonObject);
          //error handling on the result
          boolean hasErrors = JsonResult.isOk(result);
          if (hasErrors) {
              // adding errors to msgs list
              String[] errorMessages = JsonResult.getErrorMessages (result,...);           
              fillList (msgs, errorMessages);
              return msgs;
          }
       } catch (CommunicationError er) {
           msgs.add (er...);
       }
       return msgs;
    }
 } 

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

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

Есть ли лучшие практики для реализации такого кода? Есть ли пример вокруг? Есть ли лучший способ сделать это?

2 ответа

Решение

Да, вам нужно реализовать Intent Service для этого требования

По словам разработчиков сайта

Класс IntentService предоставляет простую структуру для выполнения операции в одном фоновом потоке.

Для получения полной информации и рабочего исходного кода, перейдите через Android Docs

Благодаря ответу Дэвида.

Я только что прочитал после предложения учебник в

[1] http://code.tutsplus.com/tutorials/android-fundamentals-intentservice-basics--mobile-6183

После моих тестов я предпочел услугу (не IntentService)

и создал сервис: SubmissionService

public class SubmissionIntentService extends Service {

    private List<PendingMessage> pMsgList = new CopyOnWriteArrayList<PendingMessage>();
    private Handler handler = new Handler();
    private boolean hasAppStopped = false;
    private Runnable runner;


    public SubmissionIntentService() {
      super();
      Log.d (TAG, "Service created...");
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      PendingMessage pMessage = (PendingMessage) intent.getParcelableExtra(AppConstants.MESSAGE_OBJECT);
      synchronized (pMsgList) {
         pMsgList.add(pMessage);
      }
      if (runner == null) {
         handler.postDelayed(runner = initializeRunnable(), 500);
      }
      return Service.START_NOT_STICKY;
   }

    private void runAsLongAppIsActive (Runnable runner) {
        if (!hasAppStopped) {
           handler.postDelayed (runner, SOME_INTERVAL_CONSTANT); 
        }
    }

    private Runnable initializeRunnable() {
        Runnable result;
        result = new Runnable() {

             @Override
             public void run() {
                if (pMsgList.isEmpty()) {
                   runAsLongAppIsActive (this);
                   return; 
                }

                PendingMessage[] pMArray = null;

                synchronized(pMsgList) {
                    pMArray = pMsgList.toArray (new PendingMessage[pMsgList.size()]);
                } 
                if (pMArray==null || pMArray.length==0) {
                   runAsLongAppIsActive (this);
                   return;
                }
                Log.d (TAG, "Message List size is actually :"+pMArray.length);

                for (PendingMessage pM: pMArray) {
                     try {
                        JSONObject jsonMess = JSONSendMessage.buildOutput (pM);
                        JSONObject result = HttupUtils.sendHttpPost (WEB_URL, jsonMess);

                        boolean hasErrors = JSONResult.isOk (result);
                        if (hasErrors) {
                           //TODO: error handling in case of transmission
                           //don't remove the message from the queue
                           runAsLongAppIsActive(this); 
                           return; 
                        }
                        //remove pending transmission of the queue if success
                        synchronized (pMsgList) {
                           pMsgList.remove (pM);
                        } 
                        //inform over receiver if activity is shown
                        Intent broadcastIntent = new Intent();
                        //put data in intent
                        sendBroadcast (intent);

                        //more important
                        WayPointModel model = ModelInstance.getWayPointModel();
                        model.addToModel (pM, result);
                        model.store();

                     } catch (Exception e) {
                        continue; //try to send other messages
                     }
                }
                runAsLongAppIsActive (this);
             }

           };
        return result;
    }
}

   @Override
   public void onDestroy() {
      hasAppStopped = true;
      handler.removeCallbacks (runner);
      super.onDestroy();
   }

}

Далее я добавил ResponseReceiver:

public class ResponseReceiver extends BroadcastReceiver {
   public static final String ACTION_RESP = "MESSAGE_PROCESSED";

   @Override
   public void onReceive(Context context, Intent intent) {
      //work in progress...
   }
}

и в Деятельности, где я хочу получать информацию о событиях:

public class SomeActivity extends Activity {    
  private ResponseReceiver receiver;

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

    IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    receiver = new ResponseReceiver();
    registerReceiver(receiver, filter);
    ...
 }

}

и наконец отправлять сообщения через Http:

Intent msgIntent = new Intent(this, SubmissionIntentService.class);
msgIntent.putExtra(...);
startService(msgIntent);

не забудьте объявить службу в своем манифесте:

<service android:name="ch.xxx.app.service.SubmissionIntentService" />

Наблюдения: - Я вызвал метод startService(...) из разных Деятельностей. Конструктор вызывается только один раз. ==> У меня есть только экземпляр службы для всех видов деятельности (именно то, что мне нужно).

Что я не получаю до сих пор: - возвращать данные в Activity. Что делать, если активность в данный момент не отображается?

Другие вопросы по тегам