2010-01-28 4 views
31

Je voudrais obtenir des contacts d'utilisateur et ensuite ajouter une sorte d'expression régulière et les ajouter à une vue de liste. Je suis actuellement en mesure d'obtenir tous les contacts viaComment filtrer les résultats du résolveur de contenu dans Android?

getContentResolver().query(People.CONTENT_URI, null, null, null, null);

et les passer ensuite à une classe personnalisée qui étend SimpleCursorAdapter. Donc, je voudrais savoir comment obtenir seulement les contacts qui correspondent à une expression régulière et pas tous les contacts des utilisateurs.

Répondre

63

Au lieu de

getContentResolver().query(People.CONTENT_URI, null, null, null, null); 

vous devez utiliser quelque chose comme

final ContentResolver resolver = getContentResolver(); 
final String[] projection = { People._ID, People.NAME, People.NUMBER }; 
final String sa1 = "%A%"; // contains an "A" 
cursor = resolver.query(People.CONTENT_URI, projection, People.NAME + " LIKE ?", 
    new String[] { sa1 }, null); 

celui-ci utilise une demande paramétrés (en utilisant ?) et fournit les valeurs réelles comme un argument différent, cela évite concaténation et empêche injection SQL principalement si vous demandez le filtre à l'utilisateur. Par exemple, si vous utilisez

cursor = resolver.query(People.CONTENT_URI, projection, 
    People.NAME + " = '" + name + "'", 
    new String[] { sa1 }, null); 

Imaginez si

name = "Donald Duck' OR name = 'Mickey Mouse") // notice the " and ' 

et vous concaténez les chaînes.

+0

Merci à tous pour vos réponses, je l'apprécie vraiment. – maxsap

+2

Très belle explication, merci beaucoup! –

5

Vous pouvez interroger le fournisseur de contenu avec l'entrée de type sql, la méthode de requête est juste un wrapper pour une commande sql.

Voici un exemple où je requête pour un nom Contacts donné un nombre particulier

String [] requestedColumns = { 
      Contacts.Phones.NAME, 
      Contacts.Phones.TYPE 
    }; 

Cursor contacts = context.getContentResolver().query(
      Contacts.Phones.CONTENT_URI, 
      requestedColumns, 
      Contacts.Phones.NUMBER + "='" + phoneNumber + "'", 
      null, null); 

Notez qu'au lieu de null Je paramètres qui construisent l'instruction SQL.

Les requestColumns sont les données que je veux revenir et Contacts.Phones.NUMBER + « = « » + phoneNumber + « » » est la clause Where, donc je récupérer le nom et le type où le numéro de téléphone correspond

3

Vous devriez pouvoir mettre une clause SQLite WHERE légale comme troisième argument de la méthode query(), y compris un LIKE, mais il n'y a pas de fonction REGEXP native dans SQLite et Android ne semble pas vous permettre de définir la vôtre. Donc, selon la complexité de vos besoins, un ensemble d'autres conditions SQLite et d'expressions LIKE pourrait faire l'affaire. Voir la documentation sur query method sous ContentResolver et SQLite expressions.

1

En fait, REGEXP avec le fournisseur de contenu Calllog fonctionne (signifie que la fonction regexp() est définie pour la base de données du fournisseur de contenu https://sqlite.org/lang_expr.html#regexp)! Mais il est très lent: ~ 15 sec à travers ~ 1750 enregistrements.

String regexp = "([\\s\\S]{0,}" + 
TextUtils.join("||[\\s\\S]{0,}", numbers) + 
")"; 

cursor = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI, 
null, 
CallLog.Calls.NUMBER + " REGEXP ?", 
new String[]{regexp}, 
CallLog.Calls.DATE + " DESC" 
); 
Questions connexes