簡體   English   中英

創建自定義ContentProvider時獲取ClassNotFoundException

[英]Getting a ClassNotFoundException when creating a custom 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) {

        }
    }
}

好吧,這很愚蠢……顯然,在Android Studio設置中,找不到我正在使用的SDK,因此我必須對其進行修復。 現在一切正常!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM