ContentProvider - Grundsätzliche Verständnisfragen - Und einiges im Detail

mradlmaier

mradlmaier

Fortgeschrittenes Mitglied
17
Leider ist die SDK Doku nicht sonderlich ergiebig, was ContentProvider betrifft.
Der Doku kann ich entnehmen:
  1. ContentProvider sind dafür da, Daten an andere Apps im Android Ökosystem zu exponieren
  2. Für interne Verwendung sind sie nicht notwendig
  3. Es gibt 4 Methoden, die die übliche CRUD Datenbankanbindung ermöglichen: query(), insert(), update(), delete()
  4. URIs werden benutzt, um innerhalb dieser Methoden zu unterscheiden, welche Queries exekutiert werden, sofern es mehr als z.B. einen SELECT-query im DatabaseAdapter gibt.
  5. Das impliziert auch, das ich komplexe Datenbank-Operationen via DatabaseAdapter durchführen kann, wie z.b. eine Transaktion, die erst per SELECT überprüft, ob schon ein Datensatz existiert und in Abhängigkeit davon, entweder einen INSERT oder UPDATE Query ausführt.
  6. Ob die Daten aus einer DB oder Dateien kommen, spielt keine Rolle, prinzipiell kann der ContentProvider seine Daten vom einem DatabaseAdapter oder auch aus Dateien holen
  7. Die Signature der 4 Methoden gibt den Type an der zurückgegeben wird.
  8. Abgesehen davon kann Ich die Daten herholen wo ich will, wie ich will, solange ich sie in den entsprechende Typ wrappe, im Falle von query() ein Cursor oder eine Unterklasse von Cursor, z.B. MatrixCursor
  9. In den MatrixCursor kann ich jede beliebige Datenstruktur packen
  10. Wenn keine Permissions im Manifest definiert sind, ist jeder Zugriff erlaubt

Ist das so korrekt?
Bitte um Kommentare.

Hintergrund ist der dass ich einen Custom ContentProvider implementiert habe, der bei einfachen SELECT-Queries funktioniert, bei komplexen Tarnsaktionen (ohne Fehler im LogCat) aber nicht funktioniert:

Folgenden Code habe ich auch auf stackoverflow.com android - Execute "hybrid" transactional queries through the ContentProvider class? Is this possible? - Stack Overflow wegen der besseren Lesbarkeit des Codes duch Syntaxhighlighting gepostet.

Hier meine query() Methode aus dem Contentprovider (Merke, die URIs SAINTS, SAINT_ID, SAINTS_OF_DAY funktionieren problemlos):

Code:
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		Log.d(TAG, "*******");
		Log.d(TAG, "query()");
		Log.d(TAG, "*******");
		Log.d(TAG, "uri: " + uri.toString());
		Log.d(TAG, "sURIMatcher.match(uri) == SAINTS: " + Boolean.toString(sURIMatcher.match(uri) == SAINTS));
		Log.d(TAG, "sURIMatcher.match(uri) == SAINTS_OF_DAY: " + Boolean.toString(sURIMatcher.match(uri) == SAINTS_OF_DAY));
		Log.d(TAG, "sURIMatcher.match(uri) == SAINT_ID: " + Boolean.toString(sURIMatcher.match(uri) == SAINT_ID));
		Log.d(TAG, "sURIMatcher.match(uri) == LAYOUTS4X1: " + Boolean.toString(sURIMatcher.match(uri) == LAYOUTS4X1));
		Log.d(TAG, "sURIMatcher.match(uri) == LAYOUTS4X1_ID: " + Boolean.toString(sURIMatcher.match(uri) == LAYOUTS4X1_ID));
		SQLiteDatabase db = dbAdapter.openDatabaseForWrite();
		Cursor resultCursor = null;
		if(sURIMatcher.match(uri) == SAINT_ID || sURIMatcher.match(uri) == SAINTS || sURIMatcher.match(uri) == SAINTS_OF_DAY){

			SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
			qBuilder.setTables("saints");
			if(sURIMatcher.match(uri) == SAINT_ID){
				qBuilder.appendWhere("_id" + uri.getLastPathSegment());
			}
			resultCursor = qBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder, null);
		} else if(sURIMatcher.match(uri) == LAYOUTS4X1_ID) {
			resultCursor = dbAdapter.getOrInsertDefaultLayoutId3(
					Integer.parseInt(selectionArgs[0]), 
					Integer.parseInt(selectionArgs[1]), 
					Integer.parseInt(selectionArgs[2]), 
					Integer.parseInt(selectionArgs[3]));
		} else if (sURIMatcher.match(uri) == LAYOUTS4X1){
			Log.d(TAG, "query for all layout_id in the layouts4x1 table");
		}
		return resultCursor;
	}

Hier die entsprechnde Methode im DatabaseAdapter:
Code:
    public void insertOrUpdate3(int widgetId, int layoutId, int textColor, int borderColor){
    	Log.d(TAG, "***************");
    	Log.d(TAG, "insertOrUpdate3");
    	Log.d(TAG, "***************");
    	Cursor selectCursor = null;
    	Cursor insertCursor = null;
    	Cursor updateCursor = null;
    	db = openDatabaseForWrite();
    	//db.beginTransaction();
        try {
        	String selectSql = "SELECT layout_id FROM layouts4x1 WHERE widget_id=" + Integer.toString(widgetId);
    		Log.d(TAG, selectSql);
        	selectCursor = db.rawQuery(selectSql, null);
        	Log.d(TAG, "selectCursor.getCount(): " + Integer.toString(selectCursor.getCount()));
        	if(selectCursor.getCount() == 0){
        		// insert defaultLayoutId
        		String insertSql = "INSERT INTO layouts4x1 (widget_id, layout_id, text_color, border_color) VALUES(" 
        				+ Integer.toString(widgetId) + ", "
                		+ Integer.toString(layoutId) + ", "
                        + Integer.toString(textColor) + ", "
        				+ Integer.toString(borderColor) + ")";
        		Log.d(TAG, "insertSql: " + insertSql);
            	insertCursor = db.rawQuery(selectSql, null);
            	insertCursor.close();
            	Log.d(TAG, "Integer.toString(defaultLayoutId): " + Integer.toString(layoutId));
        	}else{
        		// update layout_id
        		String updateSql = "UPDATE layouts4x1 SET layout_id =" + Integer.toString(layoutId)
        				+ ", text_color=" + Integer.toString(textColor)
        				+ ", border_color=" + Integer.toString(borderColor)
        				+  " WHERE widget_id ="+ Integer.toString(widgetId);
        		Log.d(TAG, updateSql);
            	updateCursor = db.rawQuery(updateSql, null);
            	updateCursor.close();
            	Log.d(TAG, "Integer.toString(layoutId): " + Integer.toString(layoutId));
        	}
            //db.setTransactionSuccessful();
        } catch (RuntimeException e) {
            Log.e("TransactionalActivity", "Error in transaction", e);
            throw e;
        } finally {
            //db.endTransaction();
        	selectCursor.close();
            db.close();
        	Log.d(TAG, "*******************");
        	Log.d(TAG, "end insertOrUpdate3");
        	Log.d(TAG, "*******************");
        }
    }

Die Transaktion-Statements sind zwecks Test auskommentiert, also kann es daran nicht liegen.
Auf stackoverflow.com finde sich die Aussage, das per default, ContentProvider keine Zugriffsrestriktionen unterliegen sofern nicht anders im Manifest definiert (bei mir sind keine Permissions im Manifest festgelegt) database - ContentProvider android permission - Stack Overflow

Nachdem es keine Exceptions, keine Errors im Logcat gibt, und sich alles kompiliert, weiss ich gar nicht wo ich suchen anfangen soll, zumal, die Tasache, dass die einfachen SELECT Queries für SAINT etc. URIs funktionieren. Das belegt, das der Zugriff auf den ContentProvider prinzipiell funktioniert.

Wenn ich die DB vom Gerät runterlade und mit SQLite Expert angucke, sehe ich dass, keinerlei Daten geschrieben worden sind.

Bin um jeden Hinweis dankbar.
 
Zuletzt bearbeitet:
[GELÖST]
Das Problem lag ganz woanders. db.rawQuery() hat nicht funktioniert. Stattdessen db.insert() und db.update() benutzt, funktioniert.

Im übrigen heisst das natürlich, das obige Aussagen über ContentProvider wohl richtig sind.
 

Ähnliche Themen

D
  • djsnoopy
Antworten
6
Aufrufe
614
djsnoopy
D
M
  • MikelKatzengreis
Antworten
5
Aufrufe
117
swa00
swa00
S
Antworten
8
Aufrufe
509
swa00
swa00
Zurück
Oben Unten