创建自定义ContentProvider时获取ClassNotFoundException

时间:2013-11-17 21:19:15

标签: java android android-contentprovider

我正在Android Studio中创建一个实现自定义ContentProvider的Android应用。出于某种原因,每当我编译应用程序并在模拟器上测试它时,我收到此错误消息:

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)

我已经对此进行了一些背景研究,但还没有找到解决我问题的方法。我没有在这个项目中使用ProGuard,因此排除了该服务未保留的任何内容。任何人都可以帮我解决这个问题吗?我可能会遗漏那些显而易见的东西并且正好盯着我,但我找不到它。感谢您的任何帮助!我已经在下面列出了相关文件。

这是我的清单:

<?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>

提供者本身:

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) {

        }
    }
}

1 个答案:

答案 0 :(得分:0)

嗯这是愚蠢的...显然,在Android Studio设置中,我使用的SDK没有找到,所以我不得不修复它。现在一切正常!