Apache HTTP Components

Apache HTTP Components este un proiect open-source, dezvoltat sub licență Apache, punând la dispoziția utilizatorilor o bibliotecă Java pentru accesarea de resurse prin intermediul protocolului HTTP.

Vom folosi o versiune legacy in acest laborator. In cadrul laboratorului veti putea folosi orice alternative, precum OkHttp.

Pentru ca metodele din API-ul Apache HTTP Components să poată fi utilizate într-o aplicație Android este necesar să se specifice catre sistemul de build, în fișierul build.gradle din app:

... android { // pentru fisiere build.gradle.kt useLibrary("org.apache.http.legacy") // pentru fisiere build.gradle useLibrary 'org.apache.http.legacy' } ...

De asemenea, in android manifest trebuie sa punem permisiunea de network

<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="android.permission.INTERNET"/> ...

Pentru a evita blocarea thread-ului main, oricare din apelurile catre API-ul de HTTP va trebui executat pe un thread secundar. Va reamintim o varianta cu un Thread si un handler pentru comunicare.

public class MainActivity extends AppCompatActivity { // Handler to communicate with UI thread private Handler mainHandler = new Handler(Looper.getMainLooper()); private TextView resultTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); resultTextView = findViewById(R.id.resultTextView); // Start HTTP request when a button is clicked Button fetchButton = findViewById(R.id.fetchButton); // When the button is pressed, make the HTTP request fetchButton.setOnClickListener(v -> makeHttpRequest()); } private void makeHttpRequest() { // We create a new thread, and inside we will run the code for the HTTP API. new Thread(() -> { try { // mak mainHandler.post(() -> { // Here we can run code on the main thread, and use variables // defined in the activity such as restulTextView resultTextView.setText(result); }); } catch (Exception e) { // Handle error on main thread mainHandler.post(() -> { resultTextView.setText("Error: " + e.getMessage()); }); } }).start(); } }

GET. Urmatorul exemplu prezinta o cere simpla de tip GET.

try { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("http://jepi.cs.pub.ro/expr/expr_get.php?operation=times&t1=9&t2=2"); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String content = httpClient.execute(httpGet, responseHandler); if (content != null) { /* do something with the response */ Log.i(Constants.TAG, EntityUtils.toString(httpGetEntity)); } } catch (Exception exception) { Log.e(Constants.TAG, exception.getMessage()); if (Constants.DEBUG) { exception.printStackTrace(); } }

În situația în care se dorește transmiterea de parametri către serverul web, aceștia trebuie incluși în URL (în clar), fără a se depăși limita de 2048 de caractere și folosind numai caractere ASCII:

HttpGet httpGet = new HttpGet("http:*www.server.com?attribute1=value1&...&attributen=valuen");

POST. Urmatorul exemplu prezinta o cere simpla de tip POST.

try { HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("http://www.server.com"); /* Lista de perechi tip (atribut, valoare) care vor contine informatiile transmise de client pe baza carora serverul va genera continutul, de exemplu (user, eim), (parola, 123) */ List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("attribute1", "value1")); * ... params.add(new BasicNameValuePair("attributen", "valuen")); UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params, HTTP.UTF_8); httpPost.setEntity(urlEncodedFormEntity); HttpResponse httpPostResponse = httpClient.execute(httpPost); HttpEntity httpPostEntity = httpPostResponse.getEntity(); if (httpPostEntity != null) { * do something with the response Log.i(Constants.TAG, EntityUtils.toString(httpPostEntity)); } } catch (Exception exception) { Log.e(Constants.TAG, exception.getMessage()); if (Constants.DEBUG) { exception.printStackTrace(); } }

Prelucrarea raspunsurilor. Prelucrarea unui răspuns HTTP se poate realiza:

  • prin prelucrarea obiectului de tip HttpEntity, utilizând fluxuri de intrare/ieșire:
    BufferedReader bufferedReader = null; StringBuilder result = new StringBuilder(); try { * ... bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent())); int currentLineNumber = 0; String currentLineContent; while ((currentLineContent = bufferedReader.readLine()) != null) { currentLineNumber++; result.append(currentLineNumber).append(": ").append(currentLineContent).append("\n"); } Log.i(Constants.TAG, result.toString()); } catch (Exception exception) { Log.e(Constants.TAG, exception.getMessage()); if (Constants.DEBUG) { exception.printStackTrace(); } } finally { if(bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ioException) { Log.e(Constants.TAG, exception.getMessage()); if (Constants.DEBUG) { ioException.printStackTrace(); } } } }
  • utilizând un obiect de tip ResponseHandler, ce furnizează conținutul resursei solicitate, transmis ca parametru al metodei execute() a clasei HttpClient (pe lângă obiectul HttpGet|HttpPost)