Зробіть HTTP-запит за допомогою Android


352

Я шукав всюди, але не зміг знайти свою відповідь, чи є спосіб зробити простий запит HTTP? Я хочу надіслати запит на сторінку / скрипт PHP на одному зі своїх веб-сайтів, але я не хочу показувати веб-сторінку.

Якщо можливо, я навіть хочу це зробити у фоновому режимі (у BroadcastReceiver)


Відповіді:


477

ОНОВЛЕННЯ

Це дуже стара відповідь. Я точно не рекомендую клієнта Apache. Замість цього використовуйте або:

Оригінальний відповідь

Перш за все, запитайте дозвіл на доступ до мережі, додайте наступне у свій маніфест:

<uses-permission android:name="android.permission.INTERNET" />

Тоді найпростішим способом є використання клієнта Apache http у комплекті з Android:

    HttpClient httpclient = new DefaultHttpClient();
    HttpResponse response = httpclient.execute(new HttpGet(URL));
    StatusLine statusLine = response.getStatusLine();
    if(statusLine.getStatusCode() == HttpStatus.SC_OK){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        response.getEntity().writeTo(out);
        String responseString = out.toString();
        out.close();
        //..more logic
    } else{
        //Closes the connection.
        response.getEntity().getContent().close();
        throw new IOException(statusLine.getReasonPhrase());
    }

Якщо ви хочете, щоб вона працювала в окремій потоці, я рекомендую розширити AsyncTask:

class RequestTask extends AsyncTask<String, String, String>{

    @Override
    protected String doInBackground(String... uri) {
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response;
        String responseString = null;
        try {
            response = httpclient.execute(new HttpGet(uri[0]));
            StatusLine statusLine = response.getStatusLine();
            if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                responseString = out.toString();
                out.close();
            } else{
                //Closes the connection.
                response.getEntity().getContent().close();
                throw new IOException(statusLine.getReasonPhrase());
            }
        } catch (ClientProtocolException e) {
            //TODO Handle problems..
        } catch (IOException e) {
            //TODO Handle problems..
        }
        return responseString;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        //Do anything with response..
    }
}

Потім ви можете зробити запит:

   new RequestTask().execute("http://stackoverflow.com");

11
Ось стаття з офіційного блогу розробників андроїд на AsyncTask: android-developers.blogspot.com/2010/07/…
Austyn Mahoney

77
для пряників чи більше його фактично рекомендується використовувати HttpURLConnection над бібліотекою apache, див. android-developers.blogspot.com/2011/09/… . Його менше оподатковує акумулятор і має кращі показники
Марті

8
responseString = out.toString () повинен бути перед викликом out.close (). Насправді, ви, ймовірно, повинні мати завершений блок out.close (). Але загалом, дуже корисна відповідь (+1), дякую!
dcp

9
Як і для Honeycomb (SDK 11), асинхронний підхід - це шлях. NetworkOnMainThreadException викинуть при спробі запустити запит HTTP від основного потоку.
msrxthr

2
Ця відповідь цілком відмінна. Але я б радив не використовувати AsyncTasks для роботи в мережі. Вони можуть створювати витоки пам'яті дуже легко (і насправді поданий приклад витікає), і не надають усіх функцій, які можна очікувати для мережевих запитів. Подумайте про використання RoboSpice для подібних фонових завдань: github.com/octo-online/robospice
Snicolas

67

якщо у вас немає чітких причин обрати Apache HttpClient, слід віддати перевагу java.net.URLConnection. ви можете знайти безліч прикладів того, як ним користуватися в Інтернеті.

Ми також вдосконалили документацію на Android, починаючи з вашої оригінальної публікації: http://developer.android.com/reference/java/net/HttpURLConnection.html

і ми говорили про компроміси в офіційному блозі: http://android-developers.blogspot.com/2011/09/androids-http-clients.html


13
Чому використання Apache HttpClient не рекомендується?
Тед

4
Мій спів-змовник детально розповів про це в офіційному блозі: android-developers.blogspot.com/2011/09/…
Елліот Х'юз

@ElliottHughes: Я згоден на 100%. Не можна заперечувати, що Apache httpclient пропонує прості методи та більш скорочене уявлення про протокол, але рідне URL-з'єднання Java не є менш корисним. Маючи трохи рук, його настільки ж просто у використанні, як і httpclient, і є набагато більш портативним
Нітін Бансал

1
Насправді, якщо ви подивитеся на відео Google I / O 2010 - клієнтські програми Android REST ( youtube.com/watch?v=xHXn3Kg2IQE 57min21sec), ви побачите, що Apache HttpClient - це самий рекомендований. Я цитую Вергілія Добянчі (інженера-програміста в Google, який працює в Android Application Group) "Я б просто порадив використовувати клієнт HTTP Apache, оскільки він має більш надійну реалізацію. Тип URL-з'єднання транзакції HTTP не є найефективнішим і спосіб припинення з'єднання іноді може негативно впливати на мережу. "
Алан

46

Примітка: HTTP-клієнт Apache у комплекті з Android тепер застарілий на користь HttpURLConnection . Докладнішу інформацію див. У блозі розробників Android .

Додайте <uses-permission android:name="android.permission.INTERNET" />до свого маніфесту.

Потім ви отримаєте веб-сторінку так:

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
     readStream(in);
}
finally {
     urlConnection.disconnect();
}

Я також пропоную запустити його окремим потоком:

class RequestTask extends AsyncTask<String, String, String>{

@Override
protected String doInBackground(String... uri) {
    String responseString = null;
    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if(conn.getResponseCode() == HttpsURLConnection.HTTP_OK){
            // Do normal input or output stream reading
        }
        else {
            response = "FAILED"; // See documentation for more info on response handling
        }
    } catch (ClientProtocolException e) {
        //TODO Handle problems..
    } catch (IOException e) {
        //TODO Handle problems..
    }
    return responseString;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    //Do anything with response..
}
}

Дивіться документацію для отримання додаткової інформації щодо обробки відповідей та POST-запитів.


1
@Semmix Як так? У запитанні було задано "простий HTTP" запит, і мій код робить саме це.
kevinc

1
Я розумію, що ваш перший код коду - це копія, вставлена ​​з документів Android, але людина - це зразок / doc сміття. readStreamнавіть не визначено.
Євген К

@EugeneK Вони є, але це, мабуть, найпростіший спосіб відповісти на це питання. Виконання HTTP-запиту належним чином в Android передбачає пояснення Retrofit та OkHttp. Я думаю, що це бентежить початківців більше, ніж просто роздавати фрагмент, який технічно зробить простий HTTP-запит, навіть якщо він сконструйований погано.
kevinc

12

Найпростіший спосіб - це використання lib Android під назвою Volley

Воллі пропонує такі переваги:

Автоматичне планування мережевих запитів. Кілька паралельних мережевих з'єднань . Прозоре кешування відповідей диска та пам'яті зі стандартною когерентністю кешу HTTP. Підтримка визначення пріоритетності запитів. API запиту на скасування. Ви можете скасувати один запит, або ви можете встановити блоки або коло запитів, щоб скасувати. Легкість налаштування, наприклад, для повторних спроб та випуску. Сильне впорядкування, що спрощує правильне заповнення інтерфейсу користувача даними, отриманими асинхронно з мережі. Інструменти для налагодження та відстеження.

Ви можете надіслати запит http / https так само просто:

        // Instantiate the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(this);
        String url ="http://www.yourapi.com";
        JsonObjectRequest request = new JsonObjectRequest(url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    if (null != response) {
                         try {
                             //handle your response
                         } catch (JSONException e) {
                             e.printStackTrace();
                         }
                    }
                }
            }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        queue.add(request);

У цьому випадку вам не потрібно вважати «працювати у фоновому режимі» або «використовувати кеш» самостійно, оскільки все це вже зробив Воллі.


6
private String getToServer(String service) throws IOException {
    HttpGet httpget = new HttpGet(service);
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    return new DefaultHttpClient().execute(httpget, responseHandler);

}

З повагою


4

З ниткою:

private class LoadingThread extends Thread {
    Handler handler;

    LoadingThread(Handler h) {
        handler = h;
    }
    @Override
    public void run() {
        Message m = handler.obtainMessage();
        try {
            BufferedReader in = 
                new BufferedReader(new InputStreamReader(url.openStream()));
            String page = "";
            String inLine;

            while ((inLine = in.readLine()) != null) {
                page += inLine;
            }

            in.close();
            Bundle b = new Bundle();
            b.putString("result", page);
            m.setData(b);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        handler.sendMessage(m);
    }
}

4

Я зробив це для того, щоб веб-сервіс вимагав URL-адреси, використовуючи Gson lib:

Клієнт:

public EstabelecimentoList getListaEstabelecimentoPorPromocao(){

        EstabelecimentoList estabelecimentoList  = new EstabelecimentoList();
        try{
            URL url = new URL("http://" +  Conexao.getSERVIDOR()+ "/cardapio.online/rest/recursos/busca_estabelecimento_promocao_android");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();

            if (con.getResponseCode() != 200) {
                    throw new RuntimeException("HTTP error code : "+ con.getResponseCode());
            }

            BufferedReader br = new BufferedReader(new InputStreamReader((con.getInputStream())));
            estabelecimentoList = new Gson().fromJson(br, EstabelecimentoList.class);
            con.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return estabelecimentoList;
}

4

Подивіться на цю дивовижну нову бібліотеку, яка доступна через gradle :)

build.gradle: compile 'com.apptakk.http_request:http-request:0.1.2'

Використання:

new HttpRequestTask(
    new HttpRequest("http://httpbin.org/post", HttpRequest.POST, "{ \"some\": \"data\" }"),
    new HttpRequest.Handler() {
      @Override
      public void response(HttpResponse response) {
        if (response.code == 200) {
          Log.d(this.getClass().toString(), "Request successful!");
        } else {
          Log.e(this.getClass().toString(), "Request unsuccessful: " + response);
        }
      }
    }).execute();

https://github.com/erf/http-request


1
Схоже, що будь-яка інша бібліотека ...
Нік Галлімор

3

Використовуйте Volley, як було запропоновано вище. Додати в build.gradle (Модуль: додаток)

implementation 'com.android.volley:volley:1.1.1'

Додайте наступне в AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

І додати наступний код діяльності:

public void httpCall(String url) {

    RequestQueue queue = Volley.newRequestQueue(this);

    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // enjoy your response
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // enjoy your error status
                }
    });

    queue.add(stringRequest);
}

Він замінює http-клієнт, і це дуже просто.


2

Це новий код для HTTP-запиту Get / POST в android. HTTPClientзастаріла і може бути недоступною, як це було в моєму випадку.

Спочатку додайте дві залежності в build.gradle:

compile 'org.apache.httpcomponents:httpcore:4.4.1'
compile 'org.apache.httpcomponents:httpclient:4.5'

Потім введіть цей код ASyncTaskу doBackgroundметод.

 URL url = new URL("http://localhost:8080/web/get?key=value");
 HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
 urlConnection.setRequestMethod("GET");
 int statusCode = urlConnection.getResponseCode();
 if (statusCode ==  200) {
      InputStream it = new BufferedInputStream(urlConnection.getInputStream());
      InputStreamReader read = new InputStreamReader(it);
      BufferedReader buff = new BufferedReader(read);
      StringBuilder dta = new StringBuilder();
      String chunks ;
      while((chunks = buff.readLine()) != null)
      {
         dta.append(chunks);
      }
 }
 else
 {
     //Handle else
 }

Код може застаріти, і apache більше не підтримується в Android Platform API 28. У цьому випадку ви можете ввімкнути властивість застарілого апача в файлі Gradle Manifest або на рівні модуля. Однак рекомендується використовувати мережеву бібліотеку OKHttp, Volley або Retrofit.
Рахул Райна

1

Для мене найпростішим способом є використання бібліотеки під назвою Retrofit2

Нам просто потрібно створити інтерфейс, який містить наш спосіб запиту, параметри, а також ми можемо створити спеціальний заголовок для кожного запиту:

    public interface MyService {

      @GET("users/{user}/repos")
      Call<List<Repo>> listRepos(@Path("user") String user);

      @GET("user")
      Call<UserDetails> getUserDetails(@Header("Authorization") String   credentials);

      @POST("users/new")
      Call<User> createUser(@Body User user);

      @FormUrlEncoded
      @POST("user/edit")
      Call<User> updateUser(@Field("first_name") String first, 
                            @Field("last_name") String last);

      @Multipart
      @PUT("user/photo")
      Call<User> updateUser(@Part("photo") RequestBody photo, 
                            @Part("description") RequestBody description);

      @Headers({
        "Accept: application/vnd.github.v3.full+json",
        "User-Agent: Retrofit-Sample-App"
      })
      @GET("users/{username}")
      Call<User> getUser(@Path("username") String username);    

    }

І найкраще, що ми можемо це зробити асинхронно легко, використовуючи метод enqueue


1

Оскільки жодна з відповідей не описувала спосіб виконання запитів за допомогою OkHttp , який сьогодні є дуже популярним клієнтом http для Android та Java загалом, я надам простий приклад:

//get an instance of the client
OkHttpClient client = new OkHttpClient();

//add parameters
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://www.example.com").newBuilder();
urlBuilder.addQueryParameter("query", "stack-overflow");


String url = urlBuilder.build().toString();

//build the request
Request request = new Request.Builder().url(url).build();

//execute
Response response = client.newCall(request).execute();

Очевидною перевагою цієї бібліотеки є те, що вона резюмує нас із деякими деталями низького рівня, надаючи більш дружні та безпечні способи взаємодії з ними. Синтаксис також спрощений і дозволяє писати приємний код.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.