Autore Topic: Client/Server http.  (Letto 630 volte)

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Client/Server http.
« il: 13 Giugno 2014, 16:37:57 CEST »
0
Nell'esempio che ho riportato di sotto passo al mio server un informazione ( in questo caso l'id di uno studente ) e mi ritornano tutte le informazioni. Se io volessi passargli più dati, per esempio username e password come potrei fare?
Dovrei fare due volte questo comando?
Codice (Java): [Seleziona]
nameValuePairs.add(new BasicNameValuePair("username","ciao"));
nameValuePairs.add(new BasicNameValuePair("password","ciao1"));

Oppure sarebbe possibile passare magari l'username e la password separati dal ";" e nel file php separarli ed eseguire il controllo?

Codice (Java): [Seleziona]
public class HelloHttpPostActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final TextView textviewDatiRicevuti = (TextView) findViewById(R.id.datiRicevuti);
 
        Button buttonInviaDati = (Button) findViewById(R.id.buttonInviaDati);
        buttonInviaDati.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                //invio richiesta
                textviewDatiRicevuti.setText(inviaDati());
            }
        });
    }
 
    public String inviaDati(){
        String result = "";
        String stringaFinale = "";
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("idnomerichiesto","1"));
        InputStream is = null;
 
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
       
        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost("http://blablabla/ciao.php");
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();
        }catch(Exception e){
                Log.e("TEST", "Errore nella connessione http "+e.toString());
        }
        if(is != null){
            //converto la risposta in stringa
            try{
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                    }
                    is.close();
 
                    result=sb.toString();
            }catch(Exception e){
                    Log.e("TEST", "Errore nel convertire il risultato "+e.toString());
            }
 
            //parsing dei dati arrivati in formato json
            try{
                    JSONArray jArray = new JSONArray(result);
                    for(int i=0;i<jArray.length();i++){
                            JSONObject json_data = jArray.getJSONObject(i);
                            Log.i("TEST","id: "+json_data.getInt("id")+
                                    ", cognome: "+json_data.getString("cognome")+
                                    ", nome: "+json_data.getString("nome")
                            );
                            stringaFinale = json_data.getInt("id") + " " + json_data.getString("cognome") + " " + json_data.getString("nome") + "\n\n";
                    }
            }
            catch(JSONException e){
                    Log.e("log_tag", "Error parsing data "+e.toString());
            }
        }
        else{//is Ë null e non ho avuto risposta
 
        }
 
        return stringaFinale;
    }
}

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Re:Client/Server http.
« Risposta #1 il: 16 Giugno 2014, 20:49:33 CEST »
0
Nessuno sa rispondere? Possibile  :-o

Offline GabMarioPower

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 606
  • Respect: +153
    • Github
    • Google+
    • gabrielemariotti
    • GabMarioPower
    • Mostra profilo
  • Play Store ID:
    GAB+MARIO+DEV
  • Sistema operativo:
    Ubuntu 14.04 , Win 10
Re:Client/Server http.
« Risposta #2 il: 16 Giugno 2014, 23:26:34 CEST »
0
Codice (Java): [Seleziona]
nameValuePairs.add(new BasicNameValuePair("username","ciao"));
nameValuePairs.add(new BasicNameValuePair("password","ciao1"));

Esattamente cosi.
Hai degli errori?

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

Tu questo lo fai solo in ambiente di sviluppo per provare?

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Re:Client/Server http.
« Risposta #3 il: 16 Giugno 2014, 23:55:07 CEST »
0
Ciao, innanzi tutto voglio ringraziarti per avermi risposto.
Tu mi hai chiesto se mi da degli errori, la risposta è sì . In pratica quando provo a passare al il php dei numeri tutto funziona liscio liscio ma quando tento di passargli delle stringhe non funziona. ( Possibile che nameValuePairs.add(new BasicNameValuePair("username","ciao")); voglia solo numeri?!?

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

Questo pezzo di codice l'ho aggiunto perché prima il progetto mi dava un errore e cercando su internet sono riuscito a risolverlo con questo pezzo di codice. Comunque l'applicazione che sto creando è a puro scopo "scolastico" anche se comunque per provarla l'ho messa anche nel cellulare. C'è qualche problema?






Un altra domanda se io gli passassi due valori diversi e nel file php facessi due query di un db come faccio a mandarli due risultati. Mi spiego meglio , questo è il mio codice php:

Codice (PHP): [Seleziona]
<?php
mysql_connect("*******","********","***");
mysql_select_db("*******");
 
$q=mysql_query("SELECT * FROM Persone WHERE id=".$_REQUEST['idnomerichiesto']);
while($e=mysql_fetch_assoc($q))
        $output[]=$e;
 
print(json_encode($output));
 
mysql_close();
?>

Ecco io dopo aver fatto la query gli passo il risultato, se avessi due query come dovrei fare a passargli i risultati e a separarli nell'applicazione ( non vedo una chiave che li identifichi ) , io nel codice per prendere il risultato vado a fare

Codice (Java): [Seleziona]
  BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                    }
                    is.close();
 
                    result=sb.toString();

E poi faccio il parsing da json a stringhe così

Codice (Java): [Seleziona]
 //parsing dei dati arrivati in formato json
            try{
                    JSONArray jArray = new JSONArray(result);
                    for(int i=0;i<jArray.length();i++){
                            JSONObject json_data = jArray.getJSONObject(i);
                            Log.i("TEST","id: "+json_data.getInt("id")+
                                    ", cognome: "+json_data.getString("cognome")+
                                    ", nome: "+json_data.getString("nome")
                            );
                            stringaFinale = json_data.getInt("id") + " " + json_data.getString("cognome") + " " + json_data.getString("nome") + "\n\n";
                    }

Quindi la domanda principale è come identifico la risposta?
« Ultima modifica: 17 Giugno 2014, 00:16:29 CEST da Trotto23 »

Offline GabMarioPower

  • Moderatore globale
  • Utente senior
  • *****
  • Post: 606
  • Respect: +153
    • Github
    • Google+
    • gabrielemariotti
    • GabMarioPower
    • Mostra profilo
  • Play Store ID:
    GAB+MARIO+DEV
  • Sistema operativo:
    Ubuntu 14.04 , Win 10
Re:Client/Server http.
« Risposta #4 il: 17 Giugno 2014, 07:41:53 CEST »
0
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

Pessima soluzione.
L'errore che hai è NetworkOnMainThreadException.
NetworkOnMainThreadException | Android Developers
..the exception that is thrown when an application attempts to perform a networking operation on its main thread...

Non puoi fare chiamate come HttpClient nel MainThread , ma devi usare per esempio un AsyncTask o un Service.

Quindi la domanda principale è come identifico la risposta?

Innanzitutto se hai due risposte hai due chiamate.
Poi in response puoi sempre inserire nel tuo json un altro elemento che è la chiave che cerchi per evidenziare la risposta.



Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Client/Server http.
« Risposta #5 il: 17 Giugno 2014, 07:59:11 CEST »
0
Ma scusa, ti da' errore facendo questo?

Codice (Java): [Seleziona]
nameValuePairs.add(new BasicNameValuePair("password","123"));

Codice (PHP): [Seleziona]
$q=mysql_query("SELECT * FROM Persone WHERE id=".$_REQUEST['idnomerichiesto']);
Attenzione: questo statement è il paradiso della SQL injection (da un browser possono leggerti tutto il database e persino cancellarlo).
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Re:Client/Server http.
« Risposta #6 il: 18 Giugno 2014, 15:56:30 CEST »
0
Ma scusa, ti da' errore facendo questo?

Codice (Java): [Seleziona]
nameValuePairs.add(new BasicNameValuePair("password","123"));

Codice (PHP): [Seleziona]
$q=mysql_query("SELECT * FROM Persone WHERE id=".$_REQUEST['idnomerichiesto']);
Attenzione: questo statement è il paradiso della SQL injection (da un browser possono leggerti tutto il database e persino cancellarlo).

Come dovrei fare allora per evitare questo problema?

Per la prima risposta ( nameValuePairs ) non è che mi da errore ma nel file php mi torna null anhe se per esempio il nome maggio compare.

Codice (PHP): [Seleziona]
<?php
mysql_connect("*******","********","***");
mysql_select_db("*******");
 
$q=mysql_query("SELECT * FROM Persone WHERE nome=".$_REQUEST['nome']);
while($e=mysql_fetch_assoc($q))
        $output[]=$e;
 
print(json_encode($output));
 
mysql_close();
?>

Ci vuole l' ==?
Se faccio l'uguaglianza degli id mi funzionano (gli id sono int) mentre se faccio l'uguaglianza dei nominativi ( che sono string ) non trova nessuna uguaglianza, nessuna persona che si chiama Mario anche se nel mio db c'è il nome Mario per esempio

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Client/Server http.
« Risposta #7 il: 18 Giugno 2014, 17:13:38 CEST »
0
In quanto PHP, l'argomento sta scivolando sull'offtopic. Rispondo brevemente a quello che posso, ma per dubbi di PHP dovresti rivolgerti a community di PHP.

Per la prima risposta ( nameValuePairs ) non è che mi da errore ma nel file php mi torna null anhe se per esempio il nome maggio compare.

Strano, non vedo perchè dovrebbe succedere. Verifica cosa ricevi nel PHP.

Ci vuole l' ==?
Se faccio l'uguaglianza degli id mi funzionano (gli id sono int) mentre se faccio l'uguaglianza dei nominativi ( che sono string ) non trova nessuna uguaglianza, nessuna persona che si chiama Mario anche se nel mio db c'è il nome Mario per esempio

Questo è un problema di SQL di base. Se provi in un qualsiasi SQL manager, capisci anche perchè: le stringhe devono essere tra apici nelle query sql "raw". Ma per evitare SQL injection dovresti usare altri costrutti... basta che leggi un po' sul PHP+MYSQL.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Re:Client/Server http.
« Risposta #8 il: 19 Giugno 2014, 21:09:56 CEST »
0
Grazie mille per l'aiuto sono riuscito a sistemare tutto ed ora funziona. Ho provato a seguire il consiglio di aggiungere un Task asincrono. Pensavo di aver fatto tutto bene ma purtroppo l'app mi cresha e non capisco il motivo. Il codice di seguito.

Ho provato ad implementare una cosa del genere.
Codice (Java): [Seleziona]
public class HelloHttpPostActivity extends Activity {
    /** Called when the activity is first created. */
        ProgressBar progressBar;
    EditText User;
    EditText Password;
    TextView datiRicevuti;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        //setto la progressbar non visibile
        progressBar.setVisibility(4);
        Button buttonInviaDati = (Button) findViewById(R.id.buttonInviaDati);
        buttonInviaDati.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                //progressBar.setVisibility(4);    //--invisible
                //textviewDatiRicevuti.setText("");
                new JSONParser().execute();
            }
        });
    }
   
private class JSONParser extends AsyncTask<String, String, String> {
       protected void onPreExecute() {
             super.onPreExecute();
             //Setto la progressbar visibile
             progressBar.setVisibility(0);
             }
       
       protected String getJSONFromUrl(String username, String password) {
                ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            nameValuePairs.add(new BasicNameValuePair("cognomenomerichiesto",password));
            nameValuePairs.add(new BasicNameValuePair("idnomerichiesto",username));
            InputStream is = null;
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
            try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost("dsvdvdv");
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();
            }catch(Exception e){
                Log.e("TEST", "Errore nella connessione http "+e.toString());
            }
            //Se i dati sono presenti nel db
            if(is != null){
                return "OK";
                //login=true;
            }
            return "NO";
            //return login;
        }
       
       protected String doInBackground(String... args) {
           User = (EditText) findViewById(R.id.editText1);
           Password = (EditText) findViewById(R.id.editText2);
           datiRicevuti = (TextView) findViewById(R.id.datiRicevuti);
           String risposta = getJSONFromUrl(User.getText().toString(),Password.getText().toString());
           datiRicevuti.setText(risposta);
           return risposta;
       }
       
       protected void onPostExecute(String json) {
           progressBar.setVisibility(4);    
        }
        }
}


Non so se l'implementazione è stata giusta oppure se potevo fare di meglio, c'ho provato :)

Logcat:


Citazione
06-19 19:01:48.686: E/AndroidRuntime(1729): FATAL EXCEPTION: AsyncTask #1
06-19 19:01:48.686: E/AndroidRuntime(1729): java.lang.RuntimeException: An error occured while executing doInBackground()
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.lang.Thread.run(Thread.java:856)
06-19 19:01:48.686: E/AndroidRuntime(1729): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.View.requestLayout(View.java:15473)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.View.requestLayout(View.java:15473)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.View.requestLayout(View.java:15473)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.View.requestLayout(View.java:15473)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.view.View.requestLayout(View.java:15473)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.widget.TextView.checkForRelayout(TextView.java:6452)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.widget.TextView.setText(TextView.java:3696)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.widget.TextView.setText(TextView.java:3554)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.widget.TextView.setText(TextView.java:3529)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at it.json_comunication.HelloHttpPostActivity$JSONParser.doInBackground(HelloHttpPostActivity.java:86)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at it.json_comunication.HelloHttpPostActivity$JSONParser.doInBackground(HelloHttpPostActivity.java:1)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
06-19 19:01:48.686: E/AndroidRuntime(1729):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
06-19 19:01:48.686: E/AndroidRuntime(1729):    ... 4 more

« Ultima modifica: 19 Giugno 2014, 23:42:53 CEST da Trotto23 »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Client/Server http.
« Risposta #9 il: 19 Giugno 2014, 21:31:08 CEST »
0
La causa è questa riga del LogCat:

Citazione
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

In un AsyncTask, non puoi toccare elementi della UI nel doinbackground. Ci sono le funzione preExecute e postExecute apposta: preleva/scrivi quello che ti serve dalla UI in quelle funzioni, memorizzalo in variabili dell'AsyncTask, usa queste variabili nell'elaborazione del doinbackground.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Trotto23

  • Utente junior
  • **
  • Post: 94
  • Respect: 0
    • Mostra profilo
  • Sistema operativo:
    Windows Vista
Re:Client/Server http.
« Risposta #10 il: 19 Giugno 2014, 23:55:27 CEST »
0
Ah ok, ho capito grazie. Un chiarimento, in questa riga di codice io vado a definire tre tipi di variabili:
Codice (Java): [Seleziona]
AsyncTask<String, String, String> Da quello che ho potuto capire leggendo su internet questi sono i parametri che passo ad ogni metodo ( onPreExecute() , doInBackground() e onPostexecute. Se io volessi fare in modo che un valore buleano generato nel doInBackground mi arrivasse nel onPostExecute per magari far apparire qualcosa a video come dovrei fare?
Ho provato a cambiare :
Codice (Java): [Seleziona]
AsyncTask<String, String, String> in AsyncTask<String, String, boolean> Ma questo mi genera un errore in super.OnPreExecute (errore : The method onPreExecute() is undefined for the type Object)
Come potrei fare per risolverlo?