I'm creating an Android app in Android Studio which implements a custom ContentProvider. For some reason, whenever I go to compile the app and test it out on an emulator, I'm getting this error message:
11-17 21:12:29.918 1381-1381/com.aiorsoft.encryptic E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to get provider com.aiorsoft.encryptic.providers.AccountProvider: java.lang.ClassNotFoundException: Didn't find class "com.aiorsoft.encryptic.providers.AccountProvider" on path: DexPathList[[zip file "/data/app/com.aiorsoft.encryptic-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.aiorsoft.encryptic-2, /system/lib]]
at android.app.ActivityThread.installProvider(ActivityThread.java:4882)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4485)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4425)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.aiorsoft.encryptic.providers.AccountProvider" on path: DexPathList[[zip file "/data/app/com.aiorsoft.encryptic-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.aiorsoft.encryptic-2, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
at android.app.ActivityThread.installProvider(ActivityThread.java:4867)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4485)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4425)
at android.app.ActivityThread.access$1300(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
I've done a bit of background research into this, but have yet to come across a solution to my problem. I'm not using ProGuard in this project, so that rules out anything not being kept by that service. Can anyone help me out with this issue? I may be missing something that's obvious and staring me right in the face, but I can't find it. Thank you for any help! I've included the relevant files below.
Here's my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aiorsoft.encryptic"
android:installLocation="preferExternal"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/title_app_name"
android:theme="#style/Theme.Encryptic">
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".services.ConnectionService"
android:exported="false" />
<provider
android:name=".providers.AccountProvider"
android:authorities=".providers" />
</application>
</manifest>
And the provider itself:
package com.aiorsoft.encryptic.providers;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
public class AccountProvider extends ContentProvider {
private static final String AUTHORITY = "com.aiorsoft.encryptic.providers";
private static final String DATABASE_NAME = "accounts";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + DATABASE_NAME);
private static final int DATABASE_VERSION = 1;
private static final String TABLE_ACCOUNTS = "Account";
private static final int ACCOUNTS_ALL = 1;
private static final int ACCOUNTS_SINGLE = 2;
private interface AccountColumns extends BaseColumns {
public static final String _ID = BaseColumns._ID;
public static final String USERNAME = "username";
public static final String EMAIL = "email";
public static final String TOKEN = "token";
}
private static final String[] ALL_COLUMNS = new String[] {
AccountColumns._ID, AccountColumns.USERNAME, AccountColumns.EMAIL, AccountColumns.TOKEN
};
private static final String CREATE_SQL = "CREATE TABLE "
+ TABLE_ACCOUNTS + " ("
+ AccountColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ AccountColumns.USERNAME + " TEXT NOT NULL, "
+ AccountColumns.EMAIL + " TEXT, "
+ AccountColumns.TOKEN + " TEXT);";
private static final String USERNAME_INDEX_SQL = "CREATE INDEX "
+ AccountColumns.USERNAME + "_idx ON " + TABLE_ACCOUNTS + " ("
+ AccountColumns.USERNAME + " ASC);";
private static UriMatcher uriMatcher;
private DatabaseHelper dbHelper;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, DATABASE_NAME, ACCOUNTS_ALL);
uriMatcher.addURI(AUTHORITY, DATABASE_NAME + "/#", ACCOUNTS_SINGLE);
}
#Override
public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext());
return true;
}
#Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case ACCOUNTS_ALL:
return "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + DATABASE_NAME;
case ACCOUNTS_SINGLE:
return "vdn.android.cursor.item/vnd." + AUTHORITY + "." + DATABASE_NAME;
default:
return null;
}
}
#Override
public Uri insert(Uri uri, ContentValues values) {
Uri result = doInsert(uri, values, dbHelper.getWritableDatabase());
return result;
}
#Override
public int bulkInsert(Uri uri, ContentValues[] values) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int count = 0;
try {
db.beginTransaction();
for (ContentValues value : values) {
Uri resultUri = doInsert(uri, value, db);
if (resultUri != null) {
count++;
} else {
count = 0;
throw new SQLException("Error in bulk insert");
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
db.close();
return count;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor query;
// Fix the projection
if (projection == null) {
projection = ALL_COLUMNS;
}
// Fix sort order
if (sortOrder == null) {
sortOrder = AccountColumns._ID;
}
switch (uriMatcher.match(uri)) {
case ACCOUNTS_ALL:
query = db.query(TABLE_ACCOUNTS, projection, selection, selectionArgs, null, null, sortOrder);
db.close();
return query;
case ACCOUNTS_SINGLE:
String accountId = uri.getLastPathSegment();
selection = fixSelectionString(selection);
selectionArgs = fixSelectionArgs(selectionArgs, accountId);
query = db.query(TABLE_ACCOUNTS, projection, selection, selectionArgs, null, null, sortOrder);
db.close();
return query;
default:
throw new IllegalArgumentException("Invalid uri: " + uri);
}
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
getContext().getContentResolver().notifyChange(uri, null);
SQLiteDatabase db = dbHelper.getWritableDatabase();
int rowsAffected;
switch (uriMatcher.match(uri)) {
case ACCOUNTS_ALL:
rowsAffected = db.update(TABLE_ACCOUNTS, values, selection, selectionArgs);
break;
case ACCOUNTS_SINGLE:
String accountId = uri.getLastPathSegment();
selection = fixSelectionString(selection);
selectionArgs = fixSelectionArgs(selectionArgs, accountId);
rowsAffected = db.update(TABLE_ACCOUNTS, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Illegal URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rowsAffected;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
int rowsAffected;
switch (uriMatcher.match(uri)) {
case ACCOUNTS_ALL:
rowsAffected = db.delete(TABLE_ACCOUNTS, selection, selectionArgs);
break;
case ACCOUNTS_SINGLE:
String accountId = uri.getLastPathSegment();
selection = fixSelectionString(selection);
selectionArgs = fixSelectionArgs(selectionArgs, accountId);
rowsAffected = db.delete(TABLE_ACCOUNTS, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Illegal URI: " + uri);
}
return rowsAffected;
}
private String[] fixSelectionArgs(String[] selectionArgs, String accountId) {
String[] newSelectionArgs;
if (selectionArgs == null) {
newSelectionArgs = new String[] {accountId};
} else {
newSelectionArgs = new String[selectionArgs.length + 1];
newSelectionArgs[0] = accountId;
System.arraycopy(selectionArgs, 0, newSelectionArgs, 1, selectionArgs.length);
}
return newSelectionArgs;
}
private String fixSelectionString(String selection) {
if (selection == null) {
selection = AccountColumns._ID + " = ?";
} else {
selection = AccountColumns._ID + " = ? AND (" + selection + ")";
}
return selection;
}
private Uri doInsert(Uri uri, ContentValues values, SQLiteDatabase db) {
Uri result = null;
switch (uriMatcher.match(uri)) {
case ACCOUNTS_ALL:
long id = db.insert(TABLE_ACCOUNTS, "", values);
if (id == -1) {
throw new SQLException("Error inserting data");
}
result = Uri.withAppendedPath(uri, String.valueOf(id));
break;
}
db.close();
return result;
}
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_SQL);
db.execSQL(USERNAME_INDEX_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
Well this was stupid... Apparently, in the Android Studio settings, the SDK that I was using wasn't being found, so I had to fix that. Everything works now!
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I try to write an app with a sqlite database. The Problem is, that my app in the emulator always “Unfortunately stopped”.
The stack trace says that this was happening because of a RuntimeException. This RuntimeException is caused by a SQLiteException.
The full stack trace is:
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.passwordsavver.wahlfachprojekt, PID: 3336
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.passwordsavver.wahlfachprojekt/com.passwordsavver.wahlfachprojekt.MainScreen}: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1316)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1163)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1034)
at com.passwordsavver.wahlfachprojekt.DBAdapter.getAllRows(DBAdapter.java:142)
at com.passwordsavver.wahlfachprojekt.MainScreen.populateButtons(MainScreen.java:52)
at com.passwordsavver.wahlfachprojekt.MainScreen.onCreate(MainScreen.java:33)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Application terminated.
My Problem is, after looking multiples times over my code, I don’t know where exactly the Exception in my class occurs.
My DBHealper Class looks like this:
package com.passwordsavver.wahlfachprojekt;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
private static final String TAG = "DBAdapter";
// DB Fields
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
public static final String KEY_WEBSITENAME = "websitename";
public static final String KEY_USERNAME = "username";
public static final String KEY_PASSWORD = "password";
public static final String KEY_NOTES = "notes";
public static final String KEY_FAV = "favourites";
public static final int COL_WEBSITENAME = 1;
public static final int COL_USERNAME = 2;
public static final int COL_PASSWORD = 3;
public static final int COL_NOTES = 4;
public static final int COL_FAV = 5;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_WEBSITENAME, KEY_USERNAME, KEY_PASSWORD, KEY_NOTES, KEY_FAV};
public static final String DATABASE_NAME = "MyDb";
public static final String DATABASE_TABLE = "mainTable";
public static final int DATABASE_VERSION = 5;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + "string"
+ ");";
// Context of application who uses us.
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to the database.
public long insertRow(String websitename, String username, String password, String notes, String fav) {
// Create row's data:
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_WEBSITENAME, websitename);
initialValues.put(KEY_USERNAME, username);
initialValues.put(KEY_PASSWORD, password);
initialValues.put(KEY_NOTES, notes);
initialValues.put(KEY_FAV, fav);
// Insert it into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String websitename, String username, String password, String notes, String fav) {
String where = KEY_ROWID + "=" + rowId;
// Create row's data:
ContentValues newValues = new ContentValues();
newValues.put(KEY_WEBSITENAME, websitename);
newValues.put(KEY_USERNAME, username);
newValues.put(KEY_PASSWORD, password);
newValues.put(KEY_NOTES, notes);
newValues.put(KEY_FAV, fav);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
}
The Class in where the exception occurs looks like this:
package com.passwordsavver.wahlfachprojekt;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.database.Cursor;
import android.widget.TextView;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class MainScreen extends AppCompatActivity {
DBAdapter myDb;
String passwordAES;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
Intent intent = getIntent();
passwordAES = intent.getStringExtra("Password");
openDB();
populateButtons();
}
#Override
protected void onDestroy() {
super.onDestroy();
closeDB();
}
private void openDB() {
myDb = new DBAdapter(this);
myDb.open();
}
private void closeDB() {
myDb.close();
}
private void populateButtons() {
Cursor cursor = myDb.getAllRows();
int itemNumber = 0;
int i = 0;
if (cursor.moveToFirst()) {
do {
itemNumber++;
} while (cursor.moveToNext());
}
int ids[] = new int[itemNumber];
String aesWebsitenames[] = new String[itemNumber];
String websitenames[] = new String[itemNumber];
String aesFav[] = new String[itemNumber];
String fav[] = new String[itemNumber];
if (cursor.moveToFirst()) {
do {
ids[i] = cursor.getInt(DBAdapter.COL_ROWID);
aesWebsitenames[i] = cursor.getString(DBAdapter.COL_WEBSITENAME);
aesFav[i] = cursor.getString(DBAdapter.COL_FAV);
try
{
websitenames[i] = decrypt(passwordAES, aesWebsitenames[i]);
fav[i] = decrypt(passwordAES, aesFav[i]);
}
catch(Exception e)
{
}
i++;
} while (cursor.moveToNext());
}
i = 0;
int numCols = 1;
int numRows = itemNumber;
TableLayout table = (TableLayout)findViewById(R.id.tableForButtons);
// Favourites
int countFavourites = 0;
for(int row = 0; row < numRows; row++)
{
TableRow tableRow = new TableRow(this);
table.addView(tableRow);
if(fav[i] == "1") {
Button button = new Button(this);
button.setText(websitenames[i]);
// Make text not clip on small buttons
button.setPadding(0, 0, 0, 0);
tableRow.addView(button);
final int FINAL_ID = ids[i];
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), ViewScreen.class);
intent.putExtra("id", FINAL_ID);
intent.putExtra("Password", passwordAES);
startActivity(intent);
}
});
}
countFavourites++;
i++;
}
if(countFavourites == 0)
{
TextView txtNoFavourites = (TextView) findViewById(R.id.txtMainScreenNoFavourites);
txtNoFavourites.setVisibility(View.VISIBLE);
}
i = 0;
// Not Favourites
for(int row = 0; row < numRows; row++)
{
TableRow tableRow = new TableRow(this);
table.addView(tableRow);
for(int col = 0; col < numCols; col++)
{
if(fav[i] == "0") {
Button button = new Button(this);
button.setText(websitenames[i]);
// Make text not clip on small buttons
button.setPadding(0, 0, 0, 0);
tableRow.addView(button);
final int FINAL_ID = ids[i];
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), ViewScreen.class);
intent.putExtra("id", FINAL_ID);
intent.putExtra("Password", passwordAES);
startActivity(intent);
}
});
}
}
i++;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
Intent intent;
switch (id)
{
case R.id.action_offlinemode:
intent = new Intent(this, OptionScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_allPasswords:
intent = new Intent(this, MainScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_favorites:
break;
case R.id.action_addPassword:
intent = new Intent(this, AddScreen2.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_deleteAllPasswords:
myDb.deleteAll();
break;
case R.id.action_option:
intent = new Intent(this, OptionScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_logout:
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private String decrypt (String password, String data) throws Exception
{
SecretKeySpec key = generateKey(password);
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decodedValue = Base64.decode(data, Base64.DEFAULT);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private SecretKeySpec generateKey(String password) throws Exception
{
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = password.getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
return secretKeySpec;
}
}
Please can anybody show over my code and tell me where my error is?
Change a line of your DATABASE_CREATE_SQL string,
put a space + KEY_FAV + "string" before string make it,
+ KEY_FAV + " string"
change public static final int DATABASE_VERSION = 5; value and try again.
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + "string"
+ ");";
rewrite as
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + " string "
+ ");";
as it seems only the space issue with KEY_FAV and String.
The only change required
+ KEY_FAV + "string"
as
+ KEY_FAV + " string "
+ KEY_FAV + "string"
This line treating string all together.
Add a space before.
It would be " string"
The exception is clearly saying that
Caused by: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
So there is missing a space in front of + KEY_FAV + " string". That is why it is throwing an exception.
I'm trying to make an app that involves a database. I'm using a ContentProvider and it's crashing in the query method when it tries to getWritableDatabase.
It returns a NullPointerException. I know for a fact that the Context isn't null, since that seems to be the main cause of this kind of problem.
Here's the ContentProvider code:
package com.corvus.corvusenterprises.digimonapp;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import java.util.Arrays;
import java.util.HashSet;
import static com.corvus.corvusenterprises.digimonapp.DBHelper.presentDigimon;
/**
* Created by Jack on 01/05/2017.
*/
public class DigimonContentProvider extends ContentProvider {
private static DigimonContentProvider instance;
private DBHelper dbHelper;
private SQLiteDatabase db;
private static final int DIGIMON = 10;
private static final int DIGIMON_ID = 20;
private static final int ATTACKS = 30;
private static final int ATTACKS_ID = 40;
private static final int EVOLUTIONS = 50;
private static final int EVOLUTIONS_ID = 60;
private static final String AUTHORITY = "com.corvus.corvusenterprises.digimonapp";
private static final String BASE_PATH_DIGIMON = "digimon";
private static final String BASE_PATH_ATTACKS = "attacks";
private static final String BASE_PATH_EVOLUTIONS = "evolutions";
public static final Uri CONTENT_URI_DIGIMON = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_DIGIMON);
public static final Uri CONTENT_URI_ATTACKS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_ATTACKS);
public static final Uri CONTENT_URI_EVOLUTIONS = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH_EVOLUTIONS);
public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/digimon";
public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/digimon";
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON, DIGIMON);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_DIGIMON + "/#", DIGIMON_ID);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS, ATTACKS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_ATTACKS + "/#", ATTACKS_ID);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS, EVOLUTIONS);
sURIMatcher.addURI(AUTHORITY, BASE_PATH_EVOLUTIONS + "/#", EVOLUTIONS_ID);
}
private DigimonContentProvider()
{
}
public static DigimonContentProvider getInstance() {
if (instance == null)
instance = new DigimonContentProvider();
return instance;
}
#Override
public boolean onCreate() {
Context ctx = MyApp.getContext();
dbHelper = DBHelper.getInstance(ctx);
dbHelper.insertDigimon("Guilmon", "Guilmon", "Child/Rookie", "Virus", "Dinosaur", "TRUE","R.mipmap.guilmon.jpg");
dbHelper.insertDigimon("Growmon", "Growlmon", "Adult/Champion", "Virus", "Bigger Dinosaur", "FALSE","R.mipmap.growmon.jpg");
dbHelper.insertDigimon("Terriermon", "terriermon", "Child/Rookie", "Vaccine", "Dogbunny", "FALSE","R.mipmap.terriermon.jpg");
dbHelper.insertDigimon("Galgomon", "Gargomon", "Adult/Champion", "Vaccine", "Gunbunny", "FALSE","R.mipmap.galgomon.jpg");
dbHelper.insertDigimon("Kyubimon", "Kyubimon", "Adult/Champion", "Data", "9-Tailed Fox", "FALSE","R.mipmap.kyubimon.jpg");
dbHelper.insertDigimon("Taomon", "Taomon", "Perfect/Ultimate", "Data", "Kitsune Miko", "FALSE","R.mipmap.taomon.jpg");
dbHelper.insertDigimon("Impmon", "Impmon", "Child/Rookie", "Virus", "Kid in a purple onesie", "FALSE","R.mipmap.impmon.jpg");
dbHelper.insertDigimon("Beelzebumon", "Beelzemon", "Ultimate/Mega", "Virus", "Demon Lord of Gluttony", "FALSE","R.mipmap.beelzebumon.jpg");
presentDigimon[460] = true; presentDigimon[454] = true;
presentDigimon[1019] = true; presentDigimon[374] = true;
presentDigimon[572] = true; presentDigimon[1013] = true;
presentDigimon[507] = true; presentDigimon[100] = true;
dbHelper.insertEvolution("Guilmon", "Growmon", "");
dbHelper.insertEvolution("Terriermon", "Galgomon","");
dbHelper.insertEvolution("Kyubimon", "Taomon","");
dbHelper.insertEvolution("Impmon", "Beelzebumon", "(Warp Evolution)");
dbHelper.insertAttack("Fireball", "Pyro Sphere", "Guilmon", "Explosive Fireball");
dbHelper.insertAttack("Rock Breaker", "Rock Breaker", "Guilmon", "Claw Swipe");
dbHelper.insertAttack("Exhaust Flame", "Pyro Blaster", "Growmon", "Fire Laser");
dbHelper.insertAttack("Plasma Blade", "Dragon Slash", "Growmon", "Forearm Blades");
dbHelper.insertAttack("Blazing Fire", "Bunny Blast", "Terriermon", "Energy Blast");
dbHelper.insertAttack("Petit Twister", "Terrier Tornado", "Terriermon", "Throws Tornado");
dbHelper.insertAttack("Gatling Arm", "Gargo Laser", "Galgomon", "Fires Guns");
dbHelper.insertAttack("Dum Dum Upper", "Bunny Pummel", "Galgomon", "Fires Guns While Punching");
dbHelper.insertAttack("Koenryu", "Dragon Wheel", "Kyubimon", "Fire Dragon");
dbHelper.insertAttack("Onibidama", "Fox-Tail Inferno", "Kyubimon", "Fireballs from the tails");
dbHelper.insertAttack("Bonhitsusen", "Talisman of Light", "Taomon", "Energy Seal Laser");
dbHelper.insertAttack("Oṃ", "Talisman Spell", "Taomon", "Makes a dome shield");
dbHelper.insertAttack("Night of Fire", "Badaboom", "Impmon", "Mini-Fireballs");
dbHelper.insertAttack("Pillar of Fire", "", "Impmon", "Wall of Flames");
dbHelper.insertAttack("Double Impact", "Double Impact", "Beelzebumon", "Fires two bullets");
dbHelper.insertAttack("Darkness Claw", "", "Beelzebumon", "Kills Leomon");
db = dbHelper.getWritableDatabase();
return false;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
Uri _uri = null;
switch (sURIMatcher.match(uri)) {
case DIGIMON:
long _ID1 = db.insert(DigimonTable.DIGIMON_TABLE_NAME, "", values);
if (_ID1 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_DIGIMON, _ID1);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
case ATTACKS:
long _ID2 = db.insert(AttacksTable.ATTACKS_TABLE_NAME, "", values);
if (_ID2 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_ATTACKS, _ID2);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
case EVOLUTIONS:
long _ID3 = db.insert(EvolutionsTable.EVOLUTIONS_TABLE_NAME, "", values);
if (_ID3 > 0) {
_uri = ContentUris.withAppendedId(CONTENT_URI_EVOLUTIONS, _ID3);
MyApp.getContext().getContentResolver().notifyChange(_uri, null);
}
break;
default:
throw new SQLException("Failed to insert row into " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return _uri;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
int uriType = sURIMatcher.match(uri);
checkColumns(projection, uriType);
queryBuilder.setTables(DigimonTable.DIGIMON_TABLE_NAME + ", " + EvolutionsTable.EVOLUTIONS_TABLE_NAME + ", " + AttacksTable.ATTACKS_TABLE_NAME);
switch (uriType) {
case DIGIMON:
break;
case DIGIMON_ID:
queryBuilder.appendWhere(DigimonTable.DIGIMON_COLUMN_ID+"="+uri.getLastPathSegment());
case ATTACKS:
break;
case ATTACKS_ID:
queryBuilder.appendWhere(AttacksTable.ATTACKS_COLUMN_ID+"="+uri.getLastPathSegment());
case EVOLUTIONS:
break;
case EVOLUTIONS_ID:
queryBuilder.appendWhere(EvolutionsTable.EVOLUTIONS_COLUMN_ID+"="+uri.getLastPathSegment());
default:
throw new IllegalArgumentException("Unknown URI: "+ uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(MyApp.getContext().getContentResolver(), uri);
return cursor;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
int rowsDeleted = 0;
switch (uriType) {
case DIGIMON:
rowsDeleted = db.delete(DigimonTable.DIGIMON_TABLE_NAME, selection, selectionArgs);
break;
case DIGIMON_ID:
String id1 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
DigimonTable.DIGIMON_TABLE_NAME,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
null);
} else {
rowsDeleted = db.delete(
DigimonTable.DIGIMON_TABLE_NAME,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
+ " and " + selection,
selectionArgs);
}
break;
case ATTACKS:
rowsDeleted = db.delete(AttacksTable.ATTACKS_TABLE_NAME, selection, selectionArgs);
break;
case ATTACKS_ID:
String id2 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
AttacksTable.ATTACKS_TABLE_NAME,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
null);
} else {
rowsDeleted = db.delete(
AttacksTable.ATTACKS_TABLE_NAME,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
+ " and " + selection,
selectionArgs);
}
break;
case EVOLUTIONS:
rowsDeleted = db.delete(EvolutionsTable.EVOLUTIONS_TABLE_NAME, selection, selectionArgs);
break;
case EVOLUTIONS_ID:
String id3 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsDeleted = db.delete(
EvolutionsTable.EVOLUTIONS_TABLE_NAME,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
null);
} else {
rowsDeleted = db.delete(
EvolutionsTable.EVOLUTIONS_TABLE_NAME,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
+ " and " + selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
#Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int uriType = sURIMatcher.match(uri);
int rowsUpdated = 0;
switch (uriType) {
case DIGIMON:
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case DIGIMON_ID:
String id1 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1,
null);
} else {
rowsUpdated = db.update(DigimonTable.DIGIMON_TABLE_NAME,
values,
DigimonTable.DIGIMON_COLUMN_ID + "=" + id1
+ " and "
+ selection,
selectionArgs);
}
break;
case ATTACKS:
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case ATTACKS_ID:
String id2 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2,
null);
} else {
rowsUpdated = db.update(AttacksTable.ATTACKS_TABLE_NAME,
values,
AttacksTable.ATTACKS_COLUMN_ID + "=" + id2
+ " and "
+ selection,
selectionArgs);
}
break;
case EVOLUTIONS:
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
selection,
selectionArgs);
break;
case EVOLUTIONS_ID:
String id3 = uri.getLastPathSegment();
if (TextUtils.isEmpty(selection)) {
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3,
null);
} else {
rowsUpdated = db.update(EvolutionsTable.EVOLUTIONS_TABLE_NAME,
values,
EvolutionsTable.EVOLUTIONS_COLUMN_ID + "=" + id3
+ " and "
+ selection,
selectionArgs);
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
MyApp.getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
private void checkColumns(String[] projection, int uri) {
HashSet<String> availableColumns;
String[] availableDigimon = { DigimonTable.DIGIMON_COLUMN_ID,
DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_DUB_NAME,
DigimonTable.DIGIMON_COLUMN_LEVEL, DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,
DigimonTable.DIGIMON_COLUMN_DESCRIPTION, DigimonTable.DIGIMON_COLUMN_FAVOURITE,
DigimonTable.DIGIMON_COLUMN_PATH};
String[] availableAttacks = {AttacksTable.ATTACKS_COLUMN_ID, AttacksTable.ATTACKS_COLUMN_NAME,
AttacksTable.ATTACKS_COLUMN_DUB_NAME, AttacksTable.ATTACKS_COLUMN_DIGIMON,
AttacksTable.ATTACKS_COLUMN_DESCRIPTION};
String[] availableEvolutions = {EvolutionsTable.EVOLUTIONS_COLUMN_ID,EvolutionsTable.EVOLUTIONS_COLUMN_FROM,
EvolutionsTable.EVOLUTIONS_COLUMN_TO, EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS};
if (projection != null) {
HashSet<String> requestedColumns = new HashSet<String>(
Arrays.asList(projection));
switch(uri){
case DIGIMON:
case DIGIMON_ID: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
break;
case ATTACKS:
case ATTACKS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableAttacks));
break;
case EVOLUTIONS:
case EVOLUTIONS_ID: availableColumns = new HashSet<String>(Arrays.asList(availableEvolutions));
break;
default: availableColumns = new HashSet<String>(Arrays.asList(availableDigimon));
}
// check if all columns which are requested are available
if (!availableColumns.containsAll(requestedColumns)) {
throw new IllegalArgumentException(
"Unknown columns in projection");
}
}
}
public Cursor defaultMainMenu()
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON, new String[]{DigimonTable.DIGIMON_COLUMN_NAME, DigimonTable.DIGIMON_COLUMN_FAVOURITE}, null, null, DigimonTable.DIGIMON_COLUMN_NAME + " ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor searchMenuQuery(String search)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME,DigimonTable.DIGIMON_COLUMN_FAVOURITE},DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{search},DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor favouritesMenuQuery()
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,new String[] {DigimonTable.DIGIMON_COLUMN_NAME},DigimonTable.DIGIMON_COLUMN_FAVOURITE+" = true",null,DigimonTable.DIGIMON_COLUMN_NAME+" ASC");
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonProfileQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_DIGIMON,null,DigimonTable.DIGIMON_COLUMN_NAME+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonAttacksQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_ATTACKS,null,AttacksTable.ATTACKS_COLUMN_DIGIMON+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonEvolutionFromQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_FROM+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
public Cursor digimonEvolutionToQuery(String name)
{
Cursor cursor = MyApp.getContext().getContentResolver().query(CONTENT_URI_EVOLUTIONS,null,EvolutionsTable.EVOLUTIONS_COLUMN_TO+" = '?'",new String[]{name},null);
int dummy = cursor.getCount();
return cursor;
}
}
And here's the Logcat results:
Process: com.corvus.corvusenterprises.digimonapp, PID: 12198
java.lang.RuntimeException: Unable to get provider com.corvus.corvusenterprises.digimonapp.DigimonContentProvider: java.lang.NullPointerException
at android.app.ActivityThread.installProvider(ActivityThread.java:5084)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
at android.app.ActivityThread.access$1800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.onCreate(DigimonContentProvider.java:62)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1616)
at android.content.ContentProvider.attachInfo(ContentProvider.java:1587)
at android.app.ActivityThread.installProvider(ActivityThread.java:5081)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4673)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4613)
at android.app.ActivityThread.access$1800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:711)
at dalvik.system.NativeStart.main(Native Method)
Here's the DBHelper code, in case it helps:
package com.corvus.corvusenterprises.digimonapp;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_ATTACKS;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_DIGIMON;
import static com.corvus.corvusenterprises.digimonapp.DigimonContentProvider.CONTENT_URI_EVOLUTIONS;
/**
* Created by Jack on 01/05/2017.
*/
public class DBHelper extends SQLiteOpenHelper {
public static final String[]digimonArray = {
"Gigantic array of names"};
private static final String DATABASE_NAME = "DigimonDatabase.db";
private static final int version = 1;
private static DBHelper instance;
public static boolean[]presentDigimon = new boolean[digimonArray.length];
private DBHelper(Context context) {
super(context, DATABASE_NAME, null, version);
}
public static DBHelper getInstance(Context ctx) {
if (instance == null)
instance = new DBHelper(ctx);
return instance;
}
#Override
public void onCreate(SQLiteDatabase db) {
DigimonTable.onCreate(db);
AttacksTable.onCreate(db);
EvolutionsTable.onCreate(db);
}
public void onUpgrade(SQLiteDatabase db, int oldver, int newVer)
{
DigimonTable.onUpgrade(db,oldver,newVer);
AttacksTable.onUpgrade(db,oldver,newVer);
EvolutionsTable.onUpgrade(db,oldver,newVer);
}
public void insertDigimon(String name, String dub_name, String level, String attribute, String description, String favourite, String path)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(DigimonTable.DIGIMON_COLUMN_NAME,name);
values.put(DigimonTable.DIGIMON_COLUMN_DUB_NAME,dub_name);
values.put(DigimonTable.DIGIMON_COLUMN_LEVEL,level);
values.put(DigimonTable.DIGIMON_COLUMN_ATTRIBUTE,attribute);
values.put(DigimonTable.DIGIMON_COLUMN_DESCRIPTION,description);
values.put(DigimonTable.DIGIMON_COLUMN_FAVOURITE, favourite);
values.put(DigimonTable.DIGIMON_COLUMN_PATH,path);
dcp.insert(CONTENT_URI_DIGIMON, values);
}
public void insertAttack(String name, String dub_name, String digimon, String description)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(AttacksTable.ATTACKS_COLUMN_NAME, name);
values.put(AttacksTable.ATTACKS_COLUMN_DUB_NAME,dub_name);
values.put(AttacksTable.ATTACKS_COLUMN_DIGIMON, digimon);
values.put(AttacksTable.ATTACKS_COLUMN_DESCRIPTION, description);
dcp.insert(CONTENT_URI_ATTACKS, values);
}
public void insertEvolution(String from, String to, String conditions)
{
DigimonContentProvider dcp = DigimonContentProvider.getInstance();
ContentValues values = new ContentValues();
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_TO,to);
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_FROM,from);
values.put(EvolutionsTable.EVOLUTIONS_COLUMN_CONDITIONS,conditions);
dcp.insert(CONTENT_URI_EVOLUTIONS, values);
}
}
Any and all help appreciated. If you need more information, just let me know.
(EDITED): New version being worked on. Code updated.
(EDITED 2): Fixed a possible issue with recursive calls.
I know for a fact that the Context isn't null
How do you know that? MyApp.getContext() looks strange to me.
Try giving the Context to the ContentProvider
private Context mContext;
private DigimonContentProvider(Context context)
{
this.mContext = context;
}
private DigimonContentProvider() { }
public static DigimonContentProvider getInstance(Context context) {
if (instance == null)
instance = new DigimonContentProvider(context);
return instance;
}
#Override
public boolean onCreate() {
dbHelper = DBHelper.getInstance(this.mContext);
However, you don't need a ContentProvider to have a database, so try getting the database working without it.
It is throwing a NullPointerException because you are trying to access your ContentProvider methods directly instead of using a ContentResolver for the same.
You can abstract the code you have written in the ContentProvider to access it in an another class. And this time use a ContentResolver instance for the same.
Edit:
Maybe your problem is that your dbHelper is not singleton and you are creating an another instances of it through dbHelper.getInstance(getContext) in insert() method.
Try getting a new instance of dbHelper only in onCreate() method and not in other methods.
You can use this example: MoviesContentProvider.java
Here are is the logcat:
06-24 13:33:04.226 23618-23618/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.saleh.findmypassword, PID: 23618
java.lang.IllegalArgumentException: Unknown Uri: content://com.example.saleh.findmypassword.provider/PInfos/1
at com.example.saleh.findmypassword.PInfoProvider.update(PInfoProvider.java:161)
at android.content.ContentProvider$Transport.update(ContentProvider.java:287)
at android.content.ContentResolver.update(ContentResolver.java:1316)
at com.example.saleh.findmypassword.EditActivity$1.onClick(EditActivity.java:62)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Content Provider class:
public class PInfoProvider extends ContentProvider {
private PInfoDatabase mOpenHelper;
private static String TAG = PInfoProvider.class.getSimpleName();
private static final UriMatcher sUriMatcher = buildUriMatcher();
private static final int PINFOS = 100;
private static final int PINFOS_ID = 101;
private static UriMatcher buildUriMatcher(){
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = PInfoContract.CONTENT_AUTHORITY;
matcher.addURI(authority, "PInfos", PINFOS);
matcher.addURI(authority, "Pinfos/*", PINFOS_ID);
return matcher;
}
#Override
public boolean onCreate() {
mOpenHelper = new PInfoDatabase(getContext());
return true;
}
private void deleteDatabase(){
mOpenHelper.close();
PInfoDatabase.deleteDatabase(getContext());
mOpenHelper = new PInfoDatabase(getContext());
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
final int match = sUriMatcher.match(uri);
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(PInfoDatabase.Tables.PINFOS);
switch(match){
case PINFOS:
//do nothing
break;
case PINFOS_ID:
String id = PInfoContract.PInfos.getPInfoId(uri);
queryBuilder.appendWhere(BaseColumns._ID + "=" + id);
break;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
//projection in content provider means the list of columns you want to return.
return cursor;
}
#Override
public String getType(Uri uri) {
final int match = sUriMatcher.match(uri);
switch(match){
case PINFOS:
return PInfoContract.PInfos.CONTENT_TYPE;
case PINFOS_ID:
return PInfoContract.PInfos.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
#Override
public Uri insert(Uri uri, ContentValues values) {
//ContentValues: is a list of content values of our database such as the email and username. Contains the column names and the values we want to associate to it when we're writing to the database/
Log.v(TAG, "insert(uri=" + uri + ", values =" + values.toString());
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
switch(match){
case PINFOS: //only using the PInfo and not the ID because it's to insert only.
long recordID = db.insertOrThrow(PInfoDatabase.Tables.PINFOS, null, values); //inserts a row into the database
return PInfoContract.PInfos.buildPInfoUri(String.valueOf(recordID));
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
#Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.v(TAG, "delete(uri=" + uri);
if(uri.equals(PInfoContract.URI_TABLE)){
deleteDatabase();
return 0;
//This will be executed if the user didn't input a valid record id.
//Base content uri doesn't contain an ID nor a path.
}
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
String selectionCriteria = selection;
switch(match){
/*
case PInfo:
If this was called and didn't "break" it would change all the records in the table.
We will still leave it out because we added the database deletion code above.
break;
*/
case PINFOS_ID:
String id = PInfoContract.PInfos.getPInfoId(uri);
selectionCriteria = BaseColumns._ID + "=" + id
+ (!TextUtils.isEmpty(selection) ? "AND (" + selection + ")" : "");
return db.delete(PInfoDatabase.Tables.PINFOS, selectionCriteria, selectionArgs);
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
}
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.v(TAG, "update(uri=" + uri + ", values =" + values.toString());
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
String selectionCriteria = selection;
//We set selectionCriteria to equal selection in the case PInfo case was chosen. After all,
//we still need to record the selection.
switch(match){
case PINFOS:
//do nothing
//If this was called and didn't "break" it would change all the records in the table.
break;
case PINFOS_ID:
String id = PInfoContract.PInfos.getPInfoId(uri);
selectionCriteria = BaseColumns._ID + "=" + id
+ (!TextUtils.isEmpty(selection) ? "AND (" + selection + ")" : "");
break;
default:
throw new IllegalArgumentException("Unknown Uri: " + uri);
}
return db.update(PInfoDatabase.Tables.PINFOS, values, selectionCriteria, selectionArgs);
}
}
EditActivity class:
public class EditActivity extends FragmentActivity {
private final String LOG_TAG = EditActivity.class.getSimpleName();
private TextView mWebsiteTextView, mEmailTextView, mUsernameTextView, mPasswordTextView;
private Button mButton;
private ContentResolver mContentResolver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_edit); //same layout as the AddActivity class.
getActionBar().setDisplayHomeAsUpEnabled(true); //returns up one level rather than back to the top level
mWebsiteTextView = (TextView) findViewById(R.id.pinfoWebsite);
mEmailTextView = (TextView) findViewById(R.id.pinfoEmail);
mUsernameTextView = (TextView) findViewById(R.id.pinfoUsername);
mPasswordTextView = (TextView) findViewById((R.id.pinfoPassword));
mContentResolver = EditActivity.this.getContentResolver();
Intent intent = getIntent(); //Getting the intent that was passed to this activity from the PInfoCustomAdapter class
final String _id = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_ID);
String website = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_WEBSITE);
String email = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_EMAIL);
String username= intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_USERNAME);
String password = intent.getStringExtra(PInfoContract.PInfoColumns.PINFO_PASSWORD);
//Now to populate what's on screen:
mWebsiteTextView.setText(website);
mEmailTextView.setText(email);
mUsernameTextView.setText(username);
mPasswordTextView.setText(password);
mButton = (Button) findViewById(R.id.saveButton);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ContentValues values = new ContentValues(); //Content Values Class is used to store a set of values that the ContentResolver can process.
values.put(PInfoContract.PInfoColumns.PINFO_WEBSITE, mWebsiteTextView.getText().toString()); //.put add values ot the set & .toString() to convert it to the right format
values.put(PInfoContract.PInfoColumns.PINFO_EMAIL, mEmailTextView.getText().toString());
values.put(PInfoContract.PInfoColumns.PINFO_USERNAME, mUsernameTextView.getText().toString());
values.put(PInfoContract.PInfoColumns.PINFO_PASSWORD, mPasswordTextView.getText().toString());
Uri uri = PInfoContract.PInfos.buildPInfoUri(_id); //To know which record we're dealing with
int recordsUpdated = mContentResolver.update(uri, values, null, null);
Log.d(LOG_TAG, "Number of records updated = " + recordsUpdated);
Intent intent = new Intent(EditActivity.this, MainActivity.class);
startActivity(intent);
finish(); //always use this when the activity's process is finished
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this); //Just allows to navigate back to the parent method. So: when someone presses home it will go back to the kain menu
break;
}
return true;
}
}
The class where the uri is being created:
public class PInfoContract {
interface PInfoColumns {
String PINFO_ID = "_id";
String PINFO_WEBSITE = "PInfo_Website";
String PINFO_EMAIL = "PInfo_Email";
String PINFO_USERNAME = "PInfo_Username";
String PINFO_PASSWORD = "PInfo_Password";
}
public static final String CONTENT_AUTHORITY = "com.example.saleh.findmypassword.provider";
public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final String PATH_PINFOS = "PInfos";
public static final Uri URI_TABLE = Uri.parse(BASE_CONTENT_URI.toString() + "/" + PATH_PINFOS);
public static final String[] TOP_LEVEL_PATHS = {
PATH_PINFOS
};
public static class PInfos implements PInfoColumns, BaseColumns {
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendEncodedPath(PATH_PINFOS).build();
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd." + CONTENT_AUTHORITY + ".PInfos";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd." + CONTENT_AUTHORITY + ".PInfos";
public static Uri buildPInfoUri(String pinfoid) {
return CONTENT_URI.buildUpon().appendEncodedPath(pinfoid).build();
}
public static String getPInfoId(Uri uri) {
return uri.getPathSegments().get(1);
}
}
}
The manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.saleh.findmypassword">
<permission android:name="com.example.saleh.findmypassword.provider.READWRITE" />
<uses-permission android:name="com.example.saleh.findmypassword.provider.READWRITE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.WithActionBar">
<activity
android:name=".MainActivity"
android:label="Personal Info">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddActivity"
android:label="#string/add_pinfo_title"
android:parentActivityName=".MainActivity"
android:noHistory="true"/>
<activity
android:name=".EditActivity"
android:label="#string/edit_pinfo_title"
android:parentActivityName="com.example.saleh.findmypassword.MainActivity"
android:noHistory="true"/>
<activity
android:name=".SearchActivity"
android:label="#string/search_pinfo_title"
android:parentActivityName=".MainActivity"
android:noHistory="true"/>
<provider
android:name="com.example.saleh.findmypassword.PInfoProvider"
android:authorities="com.example.saleh.findmypassword.provider"
android:exported="true"
android:readPermission="com.example.saleh.findmypassword.provider.READWRITE"
android:writePermission="com.example.saleh.findmypassword.provider.READWRITE" />
</application>
</manifest>
Your UriMatcher is matching any text "Pinfos/*", and it should match any number "Pinfos/#"
docs
My app is supposed to save data in a database then display it in a listView.
Problem is that the listView doesn't display anything.
Looking through the error log it seems to say that it has problem saving the data.
Thanks in advance
DBAdapter
package se.welovecode.wdmmg;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
private static final String TAG = "DBAdapter"; //used for logging database version changes
// Field Names:
public static final String KEY_ROWID = "_id";
public static final String KEY_TRANSACTIONS = "transactions";
public static final String KEY_ITEM = "item";
public static final String KEY_SUM = "sum";
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_TRANSACTIONS, KEY_ITEM, KEY_SUM,};
// Column Numbers for each Field Name:
public static final int COL_ROWID = 0;
public static final int COL_TRANSACTIONS = 1;
public static final int COL_ITEM = 2;
public static final int COL_SUM = 3;
// DataBase info:
public static final String DATABASE_NAME = "db";
public static final String DATABASE_TABLE = "mainTransactions";
public static final int DATABASE_VERSION = 1; // The version number must be incremented each time a change to DB structure occurs.
//SQL statement to create database
private static final String DATABASE_CREATE_SQL =
"CREATE TABLE " + DATABASE_TABLE
+ " (" + KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ KEY_TRANSACTIONS + " TEXT NOT NULL, "
+ KEY_ITEM + " TEXT NOT NULL, "
+ KEY_SUM + " INTEGER"
+ ");";
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx) {
Context context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to be inserted into the database.
public long insertRow(String transactions) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TRANSACTIONS, transactions);
// Insert the data into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
public long insertRow2(String item) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_ITEM, item);
// Insert the data into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
public long insertRow3(int sum) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_SUM, sum);
// Insert the data into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS, where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String transaction, String item, String sum) {
String where = KEY_ROWID + "=" + rowId;
ContentValues newValues = new ContentValues();
newValues.put(KEY_TRANSACTIONS, transaction);
newValues.put(KEY_ITEM, item);
newValues.put(KEY_SUM, sum);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
#Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
}
MainActivity
package se.welovecode.wdmmg;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
DBAdapter myDB;
TextView Balance;
Double value;
ListView lwTransactions;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Balance = (TextView) findViewById(R.id.tvBalance);
refreshSum();
openDB();
populateListView();
}
#Override
protected void onResume() {
super.onResume();
refreshSum();
populateListView();
}
protected void onDestroy(){
super.onDestroy();
closeDb();
}
private void openDB(){
myDB = new DBAdapter(this);
myDB.open();
}
private void closeDb(){
myDB.close();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_add:
Intent intent = new Intent(MainActivity.this, AddTransaction.class);
startActivity(intent);
default:
return super.onOptionsItemSelected(item);
}
}
private void refreshSum(){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
value = (double) prefs.getFloat("KEY", 0f);
Balance.setText(value.toString());
}
private void populateListView(){
Cursor cursor = myDB.getAllRows();
String[] fromFieldNames = new String[]{DBAdapter.KEY_ROWID, DBAdapter.KEY_TRANSACTIONS, DBAdapter.KEY_ITEM, DBAdapter.KEY_SUM,};
int[] toViewIDs = new int[] {R.id.textViewRowID, R.id.textViewStore, R.id.textViewService, R.id.textViewCost};
SimpleCursorAdapter myCursorAdapter;
myCursorAdapter = new SimpleCursorAdapter(getBaseContext(),R.layout.item_layout, cursor, fromFieldNames,toViewIDs,0);
lwTransactions = (ListView) findViewById(R.id.lwTransactions);
lwTransactions.setAdapter(myCursorAdapter);
}
}
Errorlog
06-12 17:33:38.383 29168-29168/se.welovecode.wdmmg E/SQLiteLog﹕ (1299) abort at 7 in [INSERT INTO mainTransactions(transactions) VALUES (?)]: NOT NULL constraint failed: mainTransactions.item
06-12 17:33:38.383 29168-29168/se.welovecode.wdmmg E/SQLiteDatabase﹕ Error inserting transactions=hsns
android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: mainTransactions.item (code 1299)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:952)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1595)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1465)
at se.welovecode.wdmmg.DBAdapter.insertRow(DBAdapter.java:68)
at se.welovecode.wdmmg.AddTransaction.onClick_AddTransaction(AddTransaction.java:55)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4268)
at android.view.View.performClick(View.java:5217)
at android.view.View$PerformClick.run(View.java:20983)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6141)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
06-12 17:33:38.393 29168-29168/se.welovecode.wdmmg E/SQLiteLog﹕ (1299) abort at 6 in [INSERT INTO mainTransactions(item) VALUES (?)]: NOT NULL constraint failed: mainTransactions.transactions
06-12 17:33:38.393 29168-29168/se.welovecode.wdmmg E/SQLiteDatabase﹕ Error inserting item=bsb
android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: mainTransactions.transactions (code 1299)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:952)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1595)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1465)
at se.welovecode.wdmmg.DBAdapter.insertRow2(DBAdapter.java:76)
at se.welovecode.wdmmg.AddTransaction.onClick_AddTransaction(AddTransaction.java:58)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4268)
at android.view.View.performClick(View.java:5217)
at android.view.View$PerformClick.run(View.java:20983)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6141)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
06-12 17:33:38.393 29168-29168/se.welovecode.wdmmg E/SQLiteLog﹕ (1299) abort at 6 in [INSERT INTO mainTransactions(sum) VALUES (?)]: NOT NULL constraint failed: mainTransactions.transactions
06-12 17:33:38.393 29168-29168/se.welovecode.wdmmg E/SQLiteDatabase﹕ Error inserting sum=120
android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: mainTransactions.transactions (code 1299)
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:952)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1595)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1465)
at se.welovecode.wdmmg.DBAdapter.insertRow3(DBAdapter.java:83)
at se.welovecode.wdmmg.AddTransaction.onClick_AddTransaction(AddTransaction.java:61)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4268)
at android.view.View.performClick(View.java:5217)
at android.view.View$PerformClick.run(View.java:20983)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6141)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
U got KEY_TRANSACTIONS TEXT NOT NULL and KEY_ITEM TEXT NOT NULL
but u pass in insertRow only KEY_TRANSACTION but u need to put KEY_ITEM also
public long insertRow(String transactions) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TRANSACTIONS, transactions);
initialValues.put(KEY_ITEM, "some key item");
// Insert the data into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
or remove NOT NULL from your KEY_ITEM column constraints
IllegalArgumentException: Unknown URL content://
^ Having a nightmare with the above. I've checked my variables and paths but can't see what the issue is? Greatly appreciate any pointers!
Here's my trace.
java.lang.IllegalArgumentException: Unknown URL
content://com.purewowstudio.topmovies.data.FilmProvider/film_data
at android.content.ContentResolver.insert(ContentResolver.java:1203)
at com.purewowstudio.topmovies.data.DatabaseHelper.addFilm(DatabaseHelper.java:52)
at com.purewowstudio.topmovies.fragments.FilmList$getFilms.onPostExecute(FilmList.java:72)
at com.purewowstudio.topmovies.fragments.FilmList$getFilms.onPostExecute(FilmList.java:62)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5262)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
Content Provider
public class FilmProvider extends ContentProvider {
public static final String TABLE_NAME = "film_data";
public static final String AUTHORITY = "com.purewowstudio.topmovies.data.FilmProvider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
public static final int FILMS = 1;
public static final int FILMS_ID = 2;
public static final UriMatcher sURIMatcher =
new UriMatcher(UriMatcher.NO_MATCH);
static {
sURIMatcher.addURI(AUTHORITY, TABLE_NAME, FILMS);
sURIMatcher.addURI(AUTHORITY, TABLE_NAME + "/#",
FILMS_ID);
}
private DatabaseHelper mDB;
public boolean onCreate() {
mDB = new DatabaseHelper(getContext(), null, null, 1);
return false;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(MovieDataContract.TABLE_NAME);
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case FILMS_ID:
queryBuilder.appendWhere(MovieDataContract.FilmEntry._ID + "="
+ uri.getLastPathSegment());
break;
case FILMS:
break;
default:
throw new IllegalArgumentException("Unknown URI");
}
Cursor cursor = queryBuilder.query(mDB.getReadableDatabase(),
projection, selection, selectionArgs, null, null,
sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(),
uri);
return cursor;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
int uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = mDB.getWritableDatabase();
long id = 0;
switch (uriType) {
case FILMS:
id = sqlDB.insert(MovieDataContract.TABLE_NAME,
null, values);
break;
default:
throw new IllegalArgumentException("Unknown URI: "
+ uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(MovieDataContract.TABLE_NAME + "/" + id);
}
DatabaseHelper Class
public class DatabaseHelper extends SQLiteOpenHelper {
private ContentResolver myCR;
public DatabaseHelper(Context context, String name,
SQLiteDatabase.CursorFactory factory, int version) {
super(context, MovieDataContract.DATABASE_NAME, factory, MovieDataContract.DATABASE_VERSION);
myCR = context.getContentResolver();
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(MovieDataContract.FilmEntry.SQL_CREATE_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(MovieDataContract.FilmEntry.DELETE_TABLE);
onCreate(db);
}
public void addFilm(Film film){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_TITLE, film.getTitle());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_RATING, film.getRating());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_RUNTIME, film.getRuntime());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_CRITICS, film.getCritics());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_AUDIENCE, film.getAudience());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_SYNOPSIS, film.getSynopsis());
values.put(MovieDataContract.FilmEntry.COLUMN_FILM_PROFILE, film.getProfile());
myCR.insert(FilmProvider.CONTENT_URI, values);
db.insert(MovieDataContract.TABLE_NAME,
null,
values);
db.close();
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/TopMoviesTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DetailFragment"
android:label="#string/title_activity_detail_fragment"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.purewowstudio.topmovies.MainActivity" />
<provider
android:name=".data.filmProvider"
android:authorities="com.purewowstudio.topmovies.data.filmProvider"
android:exported="true">
</provider>
</activity>
</application>
</manifest>
First, move <provider> to be a child of <application>, not <activity>.
Second, change android:exported="true" to android:exported="false", until such time as you secure your ContentProvider. As it stands, once you fix the <provider> element location as noted above, any app can read and write anything in your provider, which is unlikely to be what the user wants.
I have added package name in authorities.that's why I got this issue.I have to add Provider name in authorities.
<provider
android:name="LoginContentProvider"
android:authorities="com.provider.name.team"
android:exported="false" />