/* * Copyright (C) 2012 Pixmob (http://github.com/pixmob) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.pixmob.freemobile.netstat.content; import static org.pixmob.freemobile.netstat.Constants.TAG; import java.util.ArrayList; import org.pixmob.freemobile.netstat.content.NetstatContract.Events; import android.content.ContentProvider; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; /** * The content provider for the application database. * @author Pixmob */ public class NetstatContentProvider extends ContentProvider { private static final String EVENTS_TABLE = "events"; private static final int EVENTS = 1; private static final int EVENT_ID = 2; private static final UriMatcher URI_MATCHER; static { URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); URI_MATCHER.addURI(NetstatContract.AUTHORITY, "events", EVENTS); URI_MATCHER.addURI(NetstatContract.AUTHORITY, "event/*", EVENT_ID); } private SQLiteOpenHelper dbHelper; @Override public boolean onCreate() { try { dbHelper = new DatabaseHelper(getContext()); } catch (Exception e) { Log.e(TAG, "Cannot create content provider", e); return false; } return true; } @Override public String getType(Uri uri) { switch (URI_MATCHER.match(uri)) { case EVENTS: return Events.CONTENT_TYPE; case EVENT_ID: return Events.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unsupported Uri: " + uri); } } @Override public ContentProviderResult[] applyBatch( ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { if (operations.isEmpty()) { return new ContentProviderResult[0]; } // Execute batch operations in a single transaction for performance. final SQLiteDatabase db = dbHelper.getWritableDatabase(); db.beginTransaction(); try { final int numOperations = operations.size(); final ContentProviderResult[] results = new ContentProviderResult[numOperations]; for (int i = 0; i < numOperations; i++) { results[i] = operations.get(i).apply(this, results, i); } db.setTransactionSuccessful(); return results; } finally { db.endTransaction(); } } @Override public Uri insert(Uri uri, ContentValues values) { final String table; final Uri contentUri; switch (URI_MATCHER.match(uri)) { case EVENTS: table = EVENTS_TABLE; contentUri = Events.CONTENT_URI; break; default: throw new IllegalArgumentException("Unsupported Uri: " + uri); } final SQLiteDatabase db = dbHelper.getWritableDatabase(); final long rowId = db.insertOrThrow(table, "notNull", values); if (rowId == -1) { throw new SQLException("Failed to insert new row"); } final Uri rowUri = Uri.withAppendedPath(contentUri, String.valueOf(rowId)); getContext().getContentResolver().notifyChange(uri, null, false); return rowUri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { final SQLiteDatabase db = dbHelper.getWritableDatabase(); final int count; switch (URI_MATCHER.match(uri)) { case EVENTS: count = db.delete(EVENTS_TABLE, selection, selectionArgs); break; case EVENT_ID: final String phoneId = uri.getPathSegments().get(1); String phoneFullSelection = Events._ID + "='" + phoneId + "'"; if (!TextUtils.isEmpty(selection)) { phoneFullSelection += " AND (" + selection + ")"; } count = db.delete(EVENTS_TABLE, phoneFullSelection, selectionArgs); break; default: throw new IllegalArgumentException("Unsupported Uri: " + uri); } getContext().getContentResolver().notifyChange(uri, null, false); return count; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String realSortOrder = sortOrder; final SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (URI_MATCHER.match(uri)) { case EVENTS: qb.setTables(EVENTS_TABLE); if (TextUtils.isEmpty(realSortOrder)) { realSortOrder = Events.TIMESTAMP + " DESC"; } break; case EVENT_ID: qb.setTables(EVENTS_TABLE); qb.appendWhere(Events._ID + "=" + uri.getPathSegments().get(1)); break; } final SQLiteDatabase db = dbHelper.getReadableDatabase(); final Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, realSortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { final SQLiteDatabase db = dbHelper.getWritableDatabase(); final int count; switch (URI_MATCHER.match(uri)) { case EVENTS: count = db.update(EVENTS_TABLE, values, selection, selectionArgs); break; case EVENT_ID: final String phoneId = uri.getPathSegments().get(1); String phoneFullSelection = Events._ID + "='" + phoneId + "'"; if (!TextUtils.isEmpty(selection)) { phoneFullSelection += " AND (" + selection + ")"; } count = db.update(EVENTS_TABLE, values, phoneFullSelection, selectionArgs); break; default: throw new IllegalArgumentException("Unsupported Uri: " + uri); } getContext().getContentResolver().notifyChange(uri, null, false); return count; } /** * This class is responsible for managing the application database. The * database schema is initialized when the it is created, and upgraded after * an application update. * @author Pixmob */ private static class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHelper(final Context context) { super(context, "netstat.db", null, 2); } @Override public void onCreate(SQLiteDatabase db) { if (!db.isReadOnly()) { String req = "CREATE TABLE " + EVENTS_TABLE + " (" + Events._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + Events.TIMESTAMP + " TIMESTAMP NOT NULL, " + Events.MOBILE_CONNECTED + " INTEGER NOT NULL, " + Events.MOBILE_OPERATOR + " TEXT, " + Events.WIFI_CONNECTED + " INTEGER NOT NULL, " + Events.BATTERY_LEVEL + " INTEGER NOT NULL, " + Events.SCREEN_ON + " INTEGER NOT NULL, " + Events.POWER_ON + " INTEGER NOT NULL)"; db.execSQL(req); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (!db.isReadOnly()) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + " which will destroy all data"); db.execSQL("DROP TABLE IF EXISTS " + EVENTS_TABLE); onCreate(db); } } } }