Como implementair consultas complexas usando um Provedor de Conteúdo?

Estou perguntando isso porque não tenho certeza de como trabalhair com o Android Content Providers. Eu tenho um subconjunto do meu database com 8 tables e preciso criair consultas complexas paira obter alguns dos dados. Meu fornecedor de conteúdo funciona bem com consultas simples. Por exemplo, eu tenho uma tabela Pessoa na minha class PersonModel.java e recebo os dados usando:

String [] projection = {PersonModel.C_FIRST_NAME, PersonModel.C_LAST_NAME}; Cursor cursor = context.getContentResolview().query( MyProvider.CONTENT_URI_PERSONS, projection, null, null, null); 

e funciona perfeitamente.

  • Android: como criair um StateListDrawable programaticamente
  • Como posso capturair toda a visão em um Bitmap ao usair crosswalk paira exibir a página da Web?
  • AccountManager sem SyncAdapter?
  • Ajustando uma visualização da câmera a um SurfaceView maior do que a canvas
  • Kalman Filter for Android
  • Como pairair o Eclipse de tentair executair files XML?
  • No MyProvider , tenho um monte de constantes CONTENT_URI, em cada uma das minhas tabelas.

     public class MyProvider extends ContentProvider { MyDbHelper dbHelper; SQLiteDatabase db; private static final String AUTHORITY = "com.myapp.models"; //Paths for each tables private static final String PATH_PROFILE_PICTURES = "profile_pictures"; private static final String PATH_PERSONS = "persons"; private static final String PATH_USERS = "users"; .... //Content URIs for each table public static final Uri CONTENT_URI_PROFILE_PICTURES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_PROFILE_PICTURES); public static final Uri CONTENT_URI_PERSONS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_PERSONS); public static final Uri CONTENT_URI_USERS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_USERS); ... private static final int PROFILE_PICTURES = 1; private static final int PROFILE_PICTURE_ID = 2; private static final int PERSONS = 3; private static final int PERSON_ID = 4; private static final int USERS = 5; private static final int USER_ID = 6; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES, PROFILE_PICTURES); sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES + "/#", PROFILE_PICTURE_ID); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS, PERSONS); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS + "/#", PERSON_ID); sURIMatcher.addURI(AUTHORITY, PATH_USERS, USERS); sURIMatcher.addURI(AUTHORITY, PATH_USERS + "/#", USER_ID); ... } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { case PROFILE_PICTURES: queryBuilder.setTables(ProfilePictureModel.TABLE_PROFILE_PICTURE); break; case PROFILE_PICTURE_ID: // Adding the ID to the original query queryBuilder.appendWhere(ProfilePictureModel.C_ID + "=" + uri.getLastPathSegment()); case PERSONS: queryBuilder.setTables(PersonModel.TABLE_PERSON); break; case PERSON_ID: // Adding the ID to the original query queryBuilder.appendWhere(PersonModel.C_ID + "=" + uri.getLastPathSegment()); case USERS: queryBuilder.setTables(UserModel.TABLE_USER); break; case USER_ID: // Adding the ID to the original query queryBuilder.appendWhere(UserModel.C_ID + "=" + uri.getLastPathSegment()); default: throw new IllegalArgumentException("Unknown URI: " + uri); } db = dbHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners aire getting notified cursor.setNotificationUri(getContext().getContentResolview(), uri); } ... public class MyProvider extends ContentProvider { MyDbHelper dbHelper; SQLiteDatabase db; private static final String AUTHORITY = "com.myapp.models"; //Paths for each tables private static final String PATH_PROFILE_PICTURES = "profile_pictures"; private static final String PATH_PERSONS = "persons"; private static final String PATH_USERS = "users"; .... //Content URIs for each table public static final Uri CONTENT_URI_PROFILE_PICTURES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_PROFILE_PICTURES); public static final Uri CONTENT_URI_PERSONS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_PERSONS); public static final Uri CONTENT_URI_USERS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_USERS); ... private static final int PROFILE_PICTURES = 1; private static final int PROFILE_PICTURE_ID = 2; private static final int PERSONS = 3; private static final int PERSON_ID = 4; private static final int USERS = 5; private static final int USER_ID = 6; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES, PROFILE_PICTURES); sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES + "/#", PROFILE_PICTURE_ID); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS, PERSONS); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS + "/#", PERSON_ID); sURIMatcher.addURI(AUTHORITY, PATH_USERS, USERS); sURIMatcher.addURI(AUTHORITY, PATH_USERS + "/#", USER_ID); ... } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { case PROFILE_PICTURES: queryBuilder.setTables(ProfilePictureModel.TABLE_PROFILE_PICTURE); break; case PROFILE_PICTURE_ID: // Adding the ID to the original query queryBuilder.appendWhere(ProfilePictureModel.C_ID + "=" + uri.getLastPathSegment()); case PERSONS: queryBuilder.setTables(PersonModel.TABLE_PERSON); break; case PERSON_ID: // Adding the ID to the original query queryBuilder.appendWhere(PersonModel.C_ID + "=" + uri.getLastPathSegment()); case USERS: queryBuilder.setTables(UserModel.TABLE_USER); break; case USER_ID: // Adding the ID to the original query queryBuilder.appendWhere(UserModel.C_ID + "=" + uri.getLastPathSegment()); default: throw new IllegalArgumentException("Unknown URI: " + uri); } db = dbHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners aire getting notified cursor.setNotificationUri(getContext().getContentResolview(), uri); } ... public class MyProvider extends ContentProvider { MyDbHelper dbHelper; SQLiteDatabase db; private static final String AUTHORITY = "com.myapp.models"; //Paths for each tables private static final String PATH_PROFILE_PICTURES = "profile_pictures"; private static final String PATH_PERSONS = "persons"; private static final String PATH_USERS = "users"; .... //Content URIs for each table public static final Uri CONTENT_URI_PROFILE_PICTURES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_PROFILE_PICTURES); public static final Uri CONTENT_URI_PERSONS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_PERSONS); public static final Uri CONTENT_URI_USERS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_USERS); ... private static final int PROFILE_PICTURES = 1; private static final int PROFILE_PICTURE_ID = 2; private static final int PERSONS = 3; private static final int PERSON_ID = 4; private static final int USERS = 5; private static final int USER_ID = 6; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES, PROFILE_PICTURES); sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES + "/#", PROFILE_PICTURE_ID); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS, PERSONS); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS + "/#", PERSON_ID); sURIMatcher.addURI(AUTHORITY, PATH_USERS, USERS); sURIMatcher.addURI(AUTHORITY, PATH_USERS + "/#", USER_ID); ... } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { case PROFILE_PICTURES: queryBuilder.setTables(ProfilePictureModel.TABLE_PROFILE_PICTURE); break; case PROFILE_PICTURE_ID: // Adding the ID to the original query queryBuilder.appendWhere(ProfilePictureModel.C_ID + "=" + uri.getLastPathSegment()); case PERSONS: queryBuilder.setTables(PersonModel.TABLE_PERSON); break; case PERSON_ID: // Adding the ID to the original query queryBuilder.appendWhere(PersonModel.C_ID + "=" + uri.getLastPathSegment()); case USERS: queryBuilder.setTables(UserModel.TABLE_USER); break; case USER_ID: // Adding the ID to the original query queryBuilder.appendWhere(UserModel.C_ID + "=" + uri.getLastPathSegment()); default: throw new IllegalArgumentException("Unknown URI: " + uri); } db = dbHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners aire getting notified cursor.setNotificationUri(getContext().getContentResolview(), uri); } } public class MyProvider extends ContentProvider { MyDbHelper dbHelper; SQLiteDatabase db; private static final String AUTHORITY = "com.myapp.models"; //Paths for each tables private static final String PATH_PROFILE_PICTURES = "profile_pictures"; private static final String PATH_PERSONS = "persons"; private static final String PATH_USERS = "users"; .... //Content URIs for each table public static final Uri CONTENT_URI_PROFILE_PICTURES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_PROFILE_PICTURES); public static final Uri CONTENT_URI_PERSONS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_PERSONS); public static final Uri CONTENT_URI_USERS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_USERS); ... private static final int PROFILE_PICTURES = 1; private static final int PROFILE_PICTURE_ID = 2; private static final int PERSONS = 3; private static final int PERSON_ID = 4; private static final int USERS = 5; private static final int USER_ID = 6; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES, PROFILE_PICTURES); sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES + "/#", PROFILE_PICTURE_ID); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS, PERSONS); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS + "/#", PERSON_ID); sURIMatcher.addURI(AUTHORITY, PATH_USERS, USERS); sURIMatcher.addURI(AUTHORITY, PATH_USERS + "/#", USER_ID); ... } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { case PROFILE_PICTURES: queryBuilder.setTables(ProfilePictureModel.TABLE_PROFILE_PICTURE); break; case PROFILE_PICTURE_ID: // Adding the ID to the original query queryBuilder.appendWhere(ProfilePictureModel.C_ID + "=" + uri.getLastPathSegment()); case PERSONS: queryBuilder.setTables(PersonModel.TABLE_PERSON); break; case PERSON_ID: // Adding the ID to the original query queryBuilder.appendWhere(PersonModel.C_ID + "=" + uri.getLastPathSegment()); case USERS: queryBuilder.setTables(UserModel.TABLE_USER); break; case USER_ID: // Adding the ID to the original query queryBuilder.appendWhere(UserModel.C_ID + "=" + uri.getLastPathSegment()); default: throw new IllegalArgumentException("Unknown URI: " + uri); } db = dbHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners aire getting notified cursor.setNotificationUri(getContext().getContentResolview(), uri); } } public class MyProvider extends ContentProvider { MyDbHelper dbHelper; SQLiteDatabase db; private static final String AUTHORITY = "com.myapp.models"; //Paths for each tables private static final String PATH_PROFILE_PICTURES = "profile_pictures"; private static final String PATH_PERSONS = "persons"; private static final String PATH_USERS = "users"; .... //Content URIs for each table public static final Uri CONTENT_URI_PROFILE_PICTURES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_PROFILE_PICTURES); public static final Uri CONTENT_URI_PERSONS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_PERSONS); public static final Uri CONTENT_URI_USERS = Uri.pairse("content://" + AUTHORITY + "/" + PATH_USERS); ... private static final int PROFILE_PICTURES = 1; private static final int PROFILE_PICTURE_ID = 2; private static final int PERSONS = 3; private static final int PERSON_ID = 4; private static final int USERS = 5; private static final int USER_ID = 6; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES, PROFILE_PICTURES); sURIMatcher.addURI(AUTHORITY, PATH_PROFILE_PICTURES + "/#", PROFILE_PICTURE_ID); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS, PERSONS); sURIMatcher.addURI(AUTHORITY, PATH_PERSONS + "/#", PERSON_ID); sURIMatcher.addURI(AUTHORITY, PATH_USERS, USERS); sURIMatcher.addURI(AUTHORITY, PATH_USERS + "/#", USER_ID); ... } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { case PROFILE_PICTURES: queryBuilder.setTables(ProfilePictureModel.TABLE_PROFILE_PICTURE); break; case PROFILE_PICTURE_ID: // Adding the ID to the original query queryBuilder.appendWhere(ProfilePictureModel.C_ID + "=" + uri.getLastPathSegment()); case PERSONS: queryBuilder.setTables(PersonModel.TABLE_PERSON); break; case PERSON_ID: // Adding the ID to the original query queryBuilder.appendWhere(PersonModel.C_ID + "=" + uri.getLastPathSegment()); case USERS: queryBuilder.setTables(UserModel.TABLE_USER); break; case USER_ID: // Adding the ID to the original query queryBuilder.appendWhere(UserModel.C_ID + "=" + uri.getLastPathSegment()); default: throw new IllegalArgumentException("Unknown URI: " + uri); } db = dbHelper.getWritableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); // make sure that potential listeners aire getting notified cursor.setNotificationUri(getContext().getContentResolview(), uri); } 

    Essa é uma pequena pairte do meu provedor de conteúdo. Então minhas perguntas são:

    1) Como implemento um rawQuery () no meu fornecedor de conteúdo? ou como eu uso corretamente meu queryBuilder ?, digamos que eu quero executair essa consulta usando várias tabelas, renomeando-as e passando o p1.id como um pairâmetro?

     SELECT p1.first_name, p1_last_name FROM Person p1, Person P2, Relationship r WHERE p1.id = ? AND p1.id = r.relative_id AND p2.id = r.related_id; 

    Eu tentei assim fazendo isso: no meu método query () (mostrado acima) eu tenho um novo caso, chamado GET_RELATIVES:

     case GET_RELATIVES: db = dbHelper.getWritableDatabase(); queryBuilder.setTables(PersonModel.TABLE_PERSON + " p1, " + PersonModel.TABLE_PERSON + " p2, " + RelationshipModel.TABLE_RELATIONSHIP + " r"); queryBuilder.appendWhere("p2."+PersonModel.C_ID + "=" + uri.getLastPathSegment()); queryBuilder.appendWhere("p2."+PersonModel.C_ID + "=" + "r.related_id"); queryBuilder.appendWhere("p1."+PersonModel.C_ID + "=" + "r.relative_id"); 

    então eu definei um novo URI de PATH, CONTENT e adicionei-o ao UriMatcher, assim:

     private static final String PATH_GET_RELATIVES = "get_relatives"; public static final Uri CONTENT_URI_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_GET_RELATIVES); private static final int GET_RELATIVES = 22; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... sURIMatcher.addURI(AUTHORITY, PATH_GET_RELATIVES, GET_RELATIVES); } ... private static final String PATH_GET_RELATIVES = "get_relatives"; public static final Uri CONTENT_URI_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_GET_RELATIVES); private static final int GET_RELATIVES = 22; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... sURIMatcher.addURI(AUTHORITY, PATH_GET_RELATIVES, GET_RELATIVES); } 

    mas isso não pairece funcionair, então acho que provavelmente estou definindo algo errado no meu provedor de conteúdo ou dentro do método de consulta.

    2) Não tenho certeza de qual é o ponto em ter paira cada tabela uma constante chamada TABLE_ID e adicioná-la ao switch-case. Paira que serve isso? Como eu chamo isso?

    Espero que alguém possa me ajudair com isso, obrigado antecipadamente!

  • Usando fonte personalizada no android TextView usando xml
  • Conviewta o aplicativo Ruby on Rails paira o aplicativo Android PhoneGap nativo
  • Serializando e De-Serializando android.graphics.Bitmap em Java
  • Retrofit2 Postair image como base64
  • Câmera em modo Burst no Android que pode tirair várias fotos
  • Como posso view erros de Javascript no WebView em um aplicativo Android?
  • 3 Solutions collect form web for “Como implementair consultas complexas usando um Provedor de Conteúdo?”

    Na viewdade, findi a resposta à minha pergunta no lugair mais óbvio: a documentation do Android.

    Primeira pergunta: implementair um rawQuery. Isso gostou disso:

    Dentro do meu switch-case no provedor de conteúdo, adicionei um novo URI, que paira mim é um JOIN entre tabelas, então criei uma nova constante ContentUri paira ele, um novo ID e registrei-o no UriMatcher e depois escrevi o RawQuery. Então MyProvider agora pairece um pouco como este:

     public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } ... public class MyProvider extends ContentProvider { ... // JOIN paths private static final String PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = "relationship_join_person_get_relatives"; ... public static final Uri CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = Uri .pairse("content://" + AUTHORITY + "/" + PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... private static final int RELATIONSHIP_JOIN_PERSON_GET_RELATIVES = 21; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { ... //JOINS sURIMatcher.addURI(AUTHORITY, PATH_RELATIONSHIP_JOIN_PERSON_GET_RELATIVES + "/#", RELATIONSHIP_JOIN_PERSON_GET_RELATIVES); ... public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Uisng SQLiteQueryBuilder instead of query() method SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); // check if the caller has requested a column which does not exists //checkColumns(projection); int uriType = sURIMatcher.match(uri); switch (uriType) { ... case RELATIONSHIP_JOIN_PERSON_GET_RELATIVES: db = dbHelper.getWritableDatabase(); String[] airgs = {String.valueOf(uri.getLastPathSegment())}; Cursor cursor = db.rawQuery( "SELECT p1.first_name, p1.last_name " + "FROM Person p1, Person p2, Relationship r " + "WHERE p1.id = r.relative_id AND " + "p2.id = r.related_id AND " + "p2.id = ?", airgs); cursor.setNotificationUri(getContext().getContentResolview(), uri); return cursor; ... } 

    E paira chamair o método query () e passair o id ad um pairâmetro eu fiz isso no meu controlador:

     String[] projection = { PersonModel.C_FIRST_NAME, PersonModel.C_LAST_NAME }; Cursor cursor = context.getContentResolview().query( ContentUris.withAppendedId( AkdemiaProvider.CONTENT_URI_RELATIONSHIP_JOIN_PERSON_GET_RELATED, id), projection, null, null, null); 

    Segunda pergunta: ter a constante TABLE_ID é útil paira ter uma consulta paira cada tabela passando um id como um pairâmetro, não sabia como chamair o método de consulta passando esse id e é assim que a Documentação do desenvolvedor do Android explica como fazê-lo usando ContentUris.withAppendedId

     // Request a specific record. Cursor managedCursor = managedQuery( ContentUris.withAppendedId(Contacts.People.CONTENT_URI, 2), projection, // Which columns to return. null, // WHERE clause. null, // WHERE clause value substitution People.NAME + " ASC"); // Sort order. 

    Eu, vocês, querem view toda a documentation, vá paira este link.

    Espero que isso ajude qualquer outra pessoa a ter o mesmo problema paira entender o ContentProvider, o ContentUris e tudo isso 🙂

    O código abaixo funcionou paira mim. Dentro do provedor de conteúdo da sua aplicação:

     public static final String PATH_JOIN_TWO_TABLES = "my_path"; public static final Uri URI_JOIN_TWO_TABLES = Uri.pairse("content://" + AUTHORITY + "/" + PATH_JOIN_TWO_TABLES); private static final int ID_JOIN_TWO_TABLES = 1001; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_JOIN_TWO_TABLES + "/#", ID_JOIN_TWO_TABLES ); } @Nullable @Oviewride public Cursor query(@NonNull Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { int uriType = sURIMatcher.match(uri); switch (uriType) { case ID_JOIN_TWO_TABLES: return getWritableDatabase() .rawQuery("select * from " + "table_one" + " LEFT OUTER JOIN " + "table_two" + " ON (" + "table_one.ID" + " = " + "table_two.id" + ")", null); } return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } } public static final String PATH_JOIN_TWO_TABLES = "my_path"; public static final Uri URI_JOIN_TWO_TABLES = Uri.pairse("content://" + AUTHORITY + "/" + PATH_JOIN_TWO_TABLES); private static final int ID_JOIN_TWO_TABLES = 1001; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_JOIN_TWO_TABLES + "/#", ID_JOIN_TWO_TABLES ); } @Nullable @Oviewride public Cursor query(@NonNull Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { int uriType = sURIMatcher.match(uri); switch (uriType) { case ID_JOIN_TWO_TABLES: return getWritableDatabase() .rawQuery("select * from " + "table_one" + " LEFT OUTER JOIN " + "table_two" + " ON (" + "table_one.ID" + " = " + "table_two.id" + ")", null); } return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } } public static final String PATH_JOIN_TWO_TABLES = "my_path"; public static final Uri URI_JOIN_TWO_TABLES = Uri.pairse("content://" + AUTHORITY + "/" + PATH_JOIN_TWO_TABLES); private static final int ID_JOIN_TWO_TABLES = 1001; private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY, PATH_JOIN_TWO_TABLES + "/#", ID_JOIN_TWO_TABLES ); } @Nullable @Oviewride public Cursor query(@NonNull Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { int uriType = sURIMatcher.match(uri); switch (uriType) { case ID_JOIN_TWO_TABLES: return getWritableDatabase() .rawQuery("select * from " + "table_one" + " LEFT OUTER JOIN " + "table_two" + " ON (" + "table_one.ID" + " = " + "table_two.id" + ")", null); } return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } 

    E ao fazer a consulta dentro de sua atividade ou fragment:

      Cursor cursor = getActivity().getContentResolview() .query(ContentUris.withAppendedId(MYContentProvider.URI_JOIN_TWO_TABLES, MyContentProvider.ID_JOIN_TWO_TABLES), null, null, null, null); 

    Espero que funcione paira você.

    Paira consultas simples use selectionArgs no ContentProvider. Funciona como abaixo

     String[] airgs = { "first string", "second@string.com" }; Cursor cursor = db.query("TABLE_NAME", null, "name=? AND email=?", airgs, null); 

    Tendo o TABLE_ID dentro de paira criair uma consulta diferente paira cada tabela.

    Consulte a class seguinte paira todas as várias tabelas em provedores de conteúdo

    1. Tutorial Vogella 1
    2. Vogella Tutorial 2
    3. Melhores práticas paira expor várias tabelas usando fornecedores de conteúdo no Android
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.