Autore Topic: query() con Content Provider  (Letto 903 volte)

Offline Vincent

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: +2
    • Mostra profilo
query() con Content Provider
« il: 25 Agosto 2011, 19:12:47 CEST »
0
Ho un problema, sto provando per la prima volta a fare una query usando il mio Content Provider.
La query è per un semplice login, quindi controllare che i dati inseriti siano nel db.
Ecco il codice nell'activity:

Codice (Java): [Seleziona]
final Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on clicks
                EditText userField, passwordField;
                userField = (EditText) findViewById(R.id.entry);
                passwordField = (EditText) findViewById(R.id.entry2);
               
                Cursor c;
                String[] projection= new String[] {
                                ProjectProvider.Utente.USER, ProjectProvider.Utente.PASS};
                String where = "username =? and password =?";
                String[] selectionArgs = new String[] {userField.getText().toString(),
                                passwordField.getText().toString()};
               

                c = getContentResolver().query(Uri.parse("content://FirstProt.ProjectPOI.ProjectProvider/Utente"), projection,
                                where, selectionArgs, null);
                int n = c.getColumnCount();
                if (n==1) {
                  Intent myIntent = new Intent(v.getContext(), schermata_S2.class);
                  startActivity(myIntent);
                  finish();
                } else {
                        alert.show();
                }
            }
        });

Questa la parte del codice Content Provider interessata:

Codice (Java): [Seleziona]
public Cursor query(Uri url, String[] projection, String selection,     String[] selectionArgs, String sort) {
                // usiamo un queryBuilder per assemblare l'interrogazione
                // questo perchË implementiamo la query e non sappiamo a priori quali colonne andremo a cercare, non possiamo
                // usare quindi la rawQuery
                SQLiteQueryBuilder queryBuilder=new SQLiteQueryBuilder();
                final int match = MATCHER.match(url);
                String orderBy = "";
                switch (match) {
                  case POI:
                        // setta su quale tabella eseguire la query
                        queryBuilder.setTables("Poi");
                        // setta quali colonne mostrare
                        queryBuilder.setProjectionMap(POI_LIST_PROJECTION);
                        if (TextUtils.isEmpty(sort)) {
                                orderBy=getDefaultSortOrderPoi();
                        } else {
                                orderBy=sort;
                        }
                  case UTENTE:
                        // setta su quale tabella eseguire la query
                        queryBuilder.setTables("Utente");
                        // setta quali colonne mostrare
                        queryBuilder.setProjectionMap(UTENTE_LIST_PROJECTION);
                        if (TextUtils.isEmpty(sort)) {
                                orderBy=getDefaultSortOrderUtente();
                        } else {
                                orderBy=sort;
                        }
                  case POI_ID:
                        // setta su quale tabella eseguire la query
                        queryBuilder.setTables("Poi");
                        //in questo caso l'url e' un POI_ID o un UTENTE_ID
                        queryBuilder.appendWhere(PoiGetIdColumnName()+"="+url.getPathSegments().get(1));
                        if (TextUtils.isEmpty(sort)) {
                                orderBy=getDefaultSortOrderPoi();
                        } else {
                                orderBy=sort;
                        }
                  case UTENTE_ID:
                        // setta su quale tabella eseguire la query
                        queryBuilder.setTables("Utente");
                        //in questo caso l'url e' un UTENTE_ID
                        queryBuilder.appendWhere(UtenteGetIdColumnName()+"="+url.getPathSegments().get(1));
                        if (TextUtils.isEmpty(sort)) {
                                orderBy=getDefaultSortOrderUtente();
                        } else {
                                orderBy=sort;
                        }
                }      


                // eseguo la query e ottengo il risultato nel cursor
                Cursor cursor=queryBuilder.query(dbPOI, projection, selection, selectionArgs, null, null, orderBy);
               
                // avvisa il cursore se da quando Ë stato creato i dati nel db sono stati modificati
                cursor.setNotificationUri(getContext().getContentResolver(), url);
                return cursor;
        }

L'errore me lo dà alla riga "queryBuilder.appendWhere(PoiGetIdColumnName()+"="+url.getPathSegments().get(1));" l'errore è "IndexOoutOfBound", il fatto è che la riga dell'errore è relativa a un risultato del match sbagliato, non riesco a capire perchè. Dovrebbe prendere il match UTENTE e prende POI_ID (fra l'altro un tipo di url con ID cosa che non c'è nell'uri passato alla query)
Vi posto il codice anche dal Matcher nel Content Provider:

Codice (Java): [Seleziona]
static {
                MATCHER=new UriMatcher(UriMatcher.NO_MATCH);
                MATCHER.addURI("FirstProt.ProjectPOI.ProjectProvider", "Poi", POI);
                MATCHER.addURI("FirstProt.ProjectPOI.ProjectProvider", "Poi/#", POI_ID);
               
                //MATCHER2=new UriMatcher(UriMatcher.NO_MATCH);
                MATCHER.addURI("FirstProt.ProjectPOI.ProjectProvider", "Utente", UTENTE);
                MATCHER.addURI("FirstProt.ProjectPOI.ProjectProvider", "Utente/*", UTENTE_ID);


Qualche idea? Grazie  ;-)

PS: ho modificato il post perchè il codice di prima fra l'altro era sbagliato.
« Ultima modifica: 25 Agosto 2011, 19:37:22 CEST da Vincent »

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:query() con Content Provider
« Risposta #1 il: 25 Agosto 2011, 19:38:44 CEST »
0
Ma la tabella effettivamente esiste?

PS: Stai per caso facendo il progetto dell'unimi? :)

[Edit] hai aggiornato il thread mentre ti stavo rispondendo. Cmq semplicemente prova a vedere il valore della variabile url

Offline Vincent

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: +2
    • Mostra profilo
Re:query() con Content Provider
« Risposta #2 il: 25 Agosto 2011, 20:02:07 CEST »
0
eheh si sto facendo il progetto unimi, anche tu del dipartimento?

Si la tabella esiste è anche popolata (il form di registrazione funziona).

Ho fatto la prova a mettere questo url: "Uri.parse("FirstProt.ProjectPOI.ProjectProvider/Utente")"
quindi eliminando il "content://" e sembra eseguire la query ma mi dà un errore sull'activity ovvero sul controllo del cursore: c.getColumnCount()   l'errore è un NullPointerException quindi immagino che il cursore sia nullo. Anche in questo caso non capisco come mai visto che inserisco dati presenti nel DB.
Fra l'altro mi chiedo, è giusto inserire un URL senza "content://"?

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:query() con Content Provider
« Risposta #3 il: 26 Agosto 2011, 09:25:01 CEST »
0
eheh si sto facendo il progetto unimi, anche tu del dipartimento?

Si :)

Citazione
Ho fatto la prova a mettere questo url: "Uri.parse("FirstProt.ProjectPOI.ProjectProvider/Utente")"
quindi eliminando il "content://" e sembra eseguire la query ma mi dà un errore sull'activity ovvero sul controllo del cursore: c.getColumnCount()   l'errore è un NullPointerException quindi immagino che il cursore sia nullo. Anche in questo caso non capisco come mai visto che inserisco dati presenti nel DB.

Devi sempre testare la condizione che l'oggetto Cursor sia diverso da null perchè se la query non restituisce nessun valore ti viene appunto ritornato null.
Comunque, perchè testi il numero di colonne? Dovresti testare il numero di righe, con il metodo getCount() ;)

Citazione
Fra l'altro mi chiedo, è giusto inserire un URL senza "content://"?

No il content uri è giusto che abbia content:// davanti.

Il codice mi sembra giusto, a meno che mi sfugga qualcosa. Se fossi in te piazzerei un po' di Log.d per vedere il flusso di esecuzione e capire dove sta l'inghippo.

Offline Vincent

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: +2
    • Mostra profilo
Re:query() con Content Provider
« Risposta #4 il: 26 Agosto 2011, 10:53:05 CEST »
0
Provo a cercare di capire l'errore.

Non capisco però una cosa, l'errore me lo da alla riga
queryBuilder.appendWhere(PoiGetIdColumnName()+"="+url.getPathSegments().get(1));

sotto il "case POI_ID", quindi vuol dire che è il matching a non funzionare in quanto gli passo un uri che dovrebbe essere un "case UTENTE". Come è possibile?
Può essere che c'è un errore nella dichiarazione nel manifest?

Codice (XML): [Seleziona]
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="FirstProt.ProjectPOI"
     android:versionCode="1"
     android:versionName="1.0">
    <application android:name ="ProtApplication"
                android:icon="@drawable/icon" android:label="@string/app_name">
                <provider android:name=".ProjectProvider"
         android:authorities="FirstProt.ProjectPOI.ProjectProvider" >
          </provider>

Offline Vincent

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: +2
    • Mostra profilo
Re:query() con Content Provider
« Risposta #5 il: 26 Agosto 2011, 11:36:52 CEST »
0
rettifico, ho messo un Log e il risultato del match è giusto, come mai allora mi da errore nel blocco "case POI_ID" che non dovrebbe eseguire?  o_O

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:query() con Content Provider
« Risposta #6 il: 26 Agosto 2011, 11:41:36 CEST »
0
Come ho fatto a non vederlo! :D

Devi mettere break; alla fine di ogni case, altrimenti ti esegue anche il case sottostante!

tipo:

Codice (Java): [Seleziona]
switch (...) {
           case 1:
                //istruzioni
               break;
           case 2:
                //istruzioni
              break;
         
 }

Offline Vincent

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: +2
    • Mostra profilo
Re:query() con Content Provider
« Risposta #7 il: 26 Agosto 2011, 11:48:25 CEST »
0
che vergogna, scusate il mio java è un po' arrugginito  :-[

In tutti gli altri switch ogni "case" termina con una return immagino sia per questo che lì l'errore non mi si presentava, corretto?

Comunque grazie mille!

PS: tu hai già dato questa materia immagino giusto? Ti faccio una domanda in mp se non ti scoccia

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:query() con Content Provider
« Risposta #8 il: 26 Agosto 2011, 11:51:25 CEST »
0
PS: tu hai già dato questa materia immagino giusto? Ti faccio una domanda in mp se non ti scoccia

Si ma non ho fatto questo progetto, ho fatto il precedente.