Где вставить код 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. Что делать, если активность в данный момент не отображается?