Решил попробовать пописать под Android, соответственно появилось очень большое количество вопросов. Кому не трудно ответьте пожалуйста.
Пытаюсь сделать, чтобы приложение работало с неким API, общение с помощью json
, но у меня не получается написать класс, как например на шарпе, в который я передаю адрес, параметры и выполняю POST
запрос, например как здесь http://stackoverflow.com/questions/4015324/http-request-with-post.
Насколько я понял приложение на Android не может выполнить POST
запрос из обычного метода, нужно использовать AsyncTask<>
- тут я вообще ничего не понял, начиная от самого синтаксиса, а именно doInBackground(String... params)
- String...
это перечисления параметров при вызове метода типа doInBackground(str1, str2, str3)
или как?
В общем я не прошу написать за меня готовый код, прошу помочь понять принцип как работать с POST
запросами в Android, хотя бы один конкретный пример: отправка POST (json)
и получение ответа так же в json
и немного теории, пжлст)).
AsyncTask
лучше один раз попробовать, и потом забыть про них. То же самое касается и HttpUrlConnection
. В настоящий момент основной библиотекой для взаимодействия с Rest сервером в Android считается Retorofti. На официальном сайте есть примеры. Так же их не мало и на сторонних ресурсах, например здесь. Приведу лишь пример POST
запроса.
Для этого нам потребуется класс-модель, в которую преобразуется полученный от сервера Json, класс-модель для тела запроса и интерфейс с методом аннотированным специальной анотацией.
Допустим сервер имеет метод, который добавляет почтовые адреса пользователю, и возвращает какую то информацию о статусе операции. В теле запроса сервер принимает обычный массив из строк, а результат возвращает в виде Json.
Сначала создаем модель ответа сервера(поля объявлены как public
с целью уменьшения кода, в реальном приложении лучше использовать private
+ get/set методы):
public class AddEmailResult {
@SerializedName("email")
public String email;
@SerializedName("primary")
public Boolean primary;
@SerializedName("verified")
public Boolean verified;
}
Теперь создаем интерфейс, через который будет происходить взаимодействие с сервером.
public interface Server {
@POST
Call<List<AddEmailResult>> addEmail(@Body List<String> emails)
}
Аннотация над методом означает что будет выполнен POST
запрос, аннотация @Body
указывает на то, что этот объект должен быть передан в теле запроса.
Далее необходимо создать сервера. Делается это так:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com") // Адрес сервера
.addConverterFactory(GsonConverterFactory.create()) // говорим ретрофиту что для сериализации необходимо использовать GSON
.build();
Server service = retrofit.create(Server.class);
Call<List<AddEmailResult>> call = service.addEmail(/*list of string*/)
call.enqueue(new Callback<List<AddEmailResult>>() {
@Override
public void onResponse(Call<List<AddEmailResult>> call, Response<List<AddEmailResult>> response) {
if (response.isSuccessful()) {
// запрос выполнился успешно, сервер вернул Status 200
} else {
// сервер вернул ошибку
}
}
@Override
public void onFailure(Call<List<AddEmailResult>> call, Throwable t) {
// ошибка во время выполнения запроса
}
});
Вызывая метод enqueue()
вы говорите что бы запрос выполнился асинхронно. В конце результат придет в переданный callback где его можно обработать.
Вот в принципе и все. Данная библиотека не ограничивается одним лишь POST
запросом, она умеет делать все, что нужно для разработки клиент-серверного приложения.
Что бы добавить retrofit к себе в проект, необходимо в build.gradle
добавить следующее:
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.google.code.gson:gson:2.6.1'
Вот простой пример отправки запроса. params это просто неограниченный массив стрингов. HttpPost принимает строку которая является адресом скрипта на сервере.
BasicNameValuePair - это просто список ключ значение того, что вы отправляете. response это то что вывел нам серверный скрипт. Совсем не обязательно делать это в AsyncTask. Но обычно делают в нем. Т.к это не моментальная операция и лучше бы ее обрабатывать в новом потоке. Если нужно что-то конкретно пояснить, напишите в комментариях. Я отвечу
String doInBackground(String... params) throws IOException {
DefaultHttpClient hc = new DefaultHttpClient();
ResponseHandler<String> res = new BasicResponseHandler();
HttpPost postMethod = new HttpPost(params[0]);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
//nameValuePairs.add(new BasicNameValuePair("ID_group", PageViewActivity.Get_list_group.get(PageViewActivity.Cur_group_position).get(0)));
nameValuePairs.add(new BasicNameValuePair("ID_group", group_id));
nameValuePairs.add(new BasicNameValuePair("Login", Login));
nameValuePairs.add(new BasicNameValuePair("Password", Password));
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
String response = hc.execute(postMethod, res);
System.out.println(response);
return response;
}
А теперь о парсинге json. response - строка с json
JSONObject jsonResponse = new JSONObject(response);
JSONArray movies = jsonResponse.getJSONArray("Resourse");
for (int i = 0; i < movies.length(); i++) {
JSONObject actor = null;
actor = movies.getJSONObject(i);
String Text = null;
Text = actor.getString("ID");
News_list.add(text);
}
Пример самого json который мы парсим можно тут увидеть. Чисто для понимания формата http://contester.ddns.is74.ru:84/Get_all_group_list.ashx
Вот ещё один пример с готовой активностью, отправляющий на сервер простой json. Скопировал из своего ответа:
public class MainActivity extends Activity {
ProgressDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new RequestTask().execute("http://www.site.ru/login.php"); // скрипт, на который посылаем запрос
}
public String getJSON(String login, String pass) // получаем json объект в виде строки
{
JSONObject bot = new JSONObject();
try {
bot.put("Login", login);
bot.put("Password", pass);
} catch (JSONException e) {
e.printStackTrace();
}
return bot.toString();
}
public class RequestTask extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
try {
DefaultHttpClient hc = new DefaultHttpClient();
ResponseHandler<String> res = new BasicResponseHandler();
HttpPost postMethod = new HttpPost(params[0]);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
// ключ - "json", параметр - json в виде строки
nameValuePairs.add(new BasicNameValuePair("json", getJSON("userlogin", "userpass")));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs, "UTF-8");
postMethod.setEntity(entity);
return hc.execute(postMethod, res);
} catch (Exception e) {
System.out.println("Exp=" + e);
}
return null;
}
@Override
protected void onPostExecute(String res) {
dialog.dismiss();
// res - ответ сервера
super.onPostExecute(res);
}
@Override
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Ожидание");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
super.onPreExecute();
}
}
}
Обработать запрос можно, например, на PHP:
<?php
$json = $_POST['json']; // получаем json объект
$array = json_decode($json, true); // преобразуем его в ассоциативный массив
// получаем из него данные
$login = $array['Login'];
$pass = $array['Password'];
// дальше уже делаем то, что нужно
file_put_contents('login.txt', "$login\n$pass");
?>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
имеется XML файл matchxml, через curl легко отправить POST и добавить в базу
Хотелось бы узнать: какую строку возвращает substring(0, 0), если вызывающая строка состоит только из одного символа?