Failed to find provider info for <custom provider>
Asked Answered
H

3

7

I have read just about everything there is to find here on this issue, not getting past this.

I have a simple app starting with the MainActivity, my Content Provider is correctly defined in AndroidManifest.xml, the ContentProvider class seems alrighty...this has been tested on a nexus i9250 running 4.3 and an Asus Memo Pad running 4.2.1 as well as VDevices running Jelly Bean. The App runs in every instance and does not crash, the only thing the LogCat gives me is "Failed to find provider info for de.somename.provider" at the point where one of my fragments tries to query the Content Provider and get a cursor. Here the Code:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.somename.hvk3"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="14"
              android:targetSdkVersion="18" />

    <application android:allowBackup="true"
                 android:icon="@drawable/ic_launcher"
                 android:label="@string/app_name"
                 android:theme="@style/AppTheme" >
        <activity android:name="de.somename.hvk3.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="de.somename.hvk3.UserSettingActivity"
                  android:label="@string/settings" ></activity>
        <provider android:authorities="de.somename.provider"
                  android:enabled="true"
                  android:multiprocess="true"
                  android:name=".hvkContentProvider"
                  android:exported="true" ></provider>
    </application>
</manifest>

hvkContentProvider.java

public class hvkContentProvider extends ContentProvider {

    private static final String DATABASE_NAME = "hvkDB";
    private static final int DATABASE_VERSION = 1;
    public static final String Authority = "de.somename.provider";
    public static final String ElementPath = "/hv_kontakte";
    public static final Uri CONTENT_URI = Uri.parse("content://" + Authority + ElementPath);
    private static final int ALLROWS = 1;
    private static final int SINGLE_ROW = 2;
    
    private static final UriMatcher suriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static{
        suriMatcher.addURI("de.somename.provider", ElementPath, ALLROWS);
        suriMatcher.addURI("de.somename.provider", ElementPath + "/#", SINGLE_ROW);
    }
    
    public static final String KEY_ID = "_id";
    public static final String KEY_TYPE = "type";
    public static final String KEY_CLTYP = "cltyp";
    public static final String KEY_MDT = "mdt";
    public static final String KEY_OBJ = "obj";
    public static final String KEY_VTR = "vtr";
    public static final String KEY_FKZ = "fkz";
    public static final String KEY_NAME = "name";
    public static final String KEY_VNAME = "vname";
    public static final String KEY_TEL = "tel";
    public static final String KEY_FAX = "fax";
    public static final String KEY_MOBIL = "mobil";
    public static final String KEY_EMAIL = "email";
    
    private MySQLiteOpenHelper myOpenHelper;
    
    @Override
    public boolean onCreate() {
        
        myOpenHelper = new MySQLiteOpenHelper(getContext(), DATABASE_NAME, null, DATABASE_VERSION);
        return true;
    }
    
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        
        SQLiteDatabase db = myOpenHelper.getReadableDatabase();
        
        String groupBy = null;
        String having = null;
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setTables(MySQLiteOpenHelper.DATABASE_TABLE);
        
        switch(suriMatcher.match(uri)){
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            queryBuilder.appendWhere(KEY_ID + "=" + rowID);
        default: break;
        }
        
        Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder);
        
        return cursor;
    }
    
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
        switch(suriMatcher.match(uri)){
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            selection = KEY_ID + "=" + rowID
                    + (!TextUtils.isEmpty(selection) ?
                    " AND (" + selection + ')' : "");
        default: break;
        }
        //To return the number of deleted items you must specify a where clause. To delete all rows and return a value pass in "1"
        if (selection == null)
            selection = "1";
        
        return db.delete(MySQLiteOpenHelper.DATABASE_TABLE, selection, selectionArgs);
    }
    
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
        String nullColumnHack = null;
        long id = db.insert(MySQLiteOpenHelper.DATABASE_TABLE, nullColumnHack, values);
        
        if(id > -1){
            Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
            getContext().getContentResolver().notifyChange(insertedId, null);
            return insertedId;
        }
        else
            return null;
    }
    
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
        
        switch(suriMatcher.match(uri)){
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            selection = KEY_ID + "=" + rowID
                + (!TextUtils.isEmpty(selection) ?
                " AND (" + selection + ')' : "");
        default: break;
        }
        
        return db.update(MySQLiteOpenHelper.DATABASE_TABLE, values, selection, selectionArgs);
    }

    @Override
    public String getType(Uri uri) {
        switch(suriMatcher.match(uri)){
        case ALLROWS:
            return "vnd.android.cursor.dir/vnd.somename.contacts";
        case SINGLE_ROW:
            return "vnd.android.cursor.item/vnd.somename.contacts";
        default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
    }
    
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        
        //Find the row ID and use it as a filename
        String rowID = uri.getPathSegments().get(1);
        
        //Create a file object in the applications external files directory
        String picsDir = Environment.DIRECTORY_PICTURES;
        File file = new File(getContext().getExternalFilesDir(picsDir), rowID);
        
        if(!file.exists()) {
            try{
                file.createNewFile();
            } catch (IOException e) {
                //Log.d(TAG, "File creation failed: " + e.getMessage());
            }
        }
        
        //Translate the mode parameter to the corresponding Parcel File Descriptor open mode
        int fileMode = 0;
        if(mode.contains("w"))
            fileMode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
        if(mode.contains("r"))
            fileMode |= ParcelFileDescriptor.MODE_READ_ONLY;
        if(mode.contains("+"))
            fileMode |= ParcelFileDescriptor.MODE_APPEND;
        
        return ParcelFileDescriptor.open(file, fileMode);
    }
    
    private class MySQLiteOpenHelper extends SQLiteOpenHelper {     //used to be static
        
        public static final String DATABASE_TABLE = "hv_kontakte";
        private static final String DATABASE_CREATE = 
                "CREATE TABLE " + DATABASE_TABLE + "(" + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                        KEY_TYPE + " TEXT, " + KEY_CLTYP + " TEXT, " + KEY_MDT + " INTEGER, " + KEY_OBJ + " INTEGER, "
                        + KEY_VTR + " INTEGER, " + KEY_FKZ + " INTEGER, " + KEY_NAME + " TEXT, " + KEY_VNAME + " TEXT, "
                        + KEY_TEL + " TEXT, " + KEY_FAX + " TEXT, " + KEY_MOBIL + " TEXT, " + KEY_EMAIL + " TEXT)";
        
        public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
        
        @Override
        public void onCreate(SQLiteDatabase database) {
            database.execSQL(DATABASE_CREATE);
            hvkContentProvider.this.insertSomeContacts();
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
            database.execSQL("DROP TABLE IF EXISTS" + DATABASE_TABLE);
            onCreate(database);
        }
    }
}

HdwFragment.java

public class HdwFragment extends Fragment{

    private SimpleCursorAdapter hdwDataAdapter;
    private ListView listview;
    public static final String ARG_SECTION_NUMBER = "section_number";
    private static final String TAG = "HdwFragment";
    public HdwFragment(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){
        
        Context context = getActivity();
        View rootView = inflater.inflate(R.layout.fragment_all,container, false);
        TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
        dummyTextView.setText("Dienstleister");
        //android.support.v4.app.LoaderManager loaderManager = getLoaderManager();
        
        Log.i(TAG, "Before getContentResolver");
        ContentResolver cr = context.getContentResolver();
        Log.i(TAG, "Before result_columns");
        String[] result_columns = new String[] {
                hvkContentProvider.KEY_ID,
                hvkContentProvider.KEY_TYPE,
                hvkContentProvider.KEY_CLTYP,
                hvkContentProvider.KEY_NAME,
                hvkContentProvider.KEY_VNAME
        };
        Log.i(TAG, "Before where,whereArgs and order");
        String where = null;
        String whereArgs[] = null;
        String order = null;
        Log.i(TAG, "Before resultCursor action");
        Log.i(TAG, "hvkContentProvider URI: " + hvkContentProvider.CONTENT_URI);
        Cursor resultCursor = cr.query(hvkContentProvider.CONTENT_URI, result_columns, where, whereArgs, order);
        Log.i(TAG, "resultCursor = " + resultCursor);
        Log.i(TAG, "Before fromColumns");
        String[] fromColumns = new String[]{
                hvkContentProvider.KEY_TYPE,
                hvkContentProvider.KEY_CLTYP,
                hvkContentProvider.KEY_NAME,
                hvkContentProvider.KEY_VNAME    
        };
        Log.i(TAG, "Before toViews");
        int[] toViews = new int[]{
            R.id.contactType,
            R.id.contactCltype,
            R.id.contactName,
            R.id.contactVname
        };
        Log.i(TAG, "Before Adapter");
        hdwDataAdapter = new SimpleCursorAdapter(getActivity(), R.layout.object_list_item, resultCursor, fromColumns, toViews, 0);
        listview = (ListView) rootView.findViewById(R.id.list_all);
        listview.setAdapter(hdwDataAdapter);
        Log.i(TAG, "Before return Layout");
        return (LinearLayout) rootView;
    }
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);
        
        //Bundle args = null;
        //loaderManager.initLoader(LOADER_ID, args, loaderCallback);
    }
}

The Method: insertSomeFunctions() i have left out since it doesn't make a difference here, gonna put a bounty on this asap. Really need to get this done.

Heyman answered 27/8, 2013 at 11:10 Comment(0)
C
18
<provider android:authorities="de.somename.provider"
    android:enabled="true"
    android:multiprocess="true"
    android:name=".hvkContentProvider"
    android:exported="true" ></provider>

From reference page on <provider>: Link

android:authorities: ......To avoid conflicts, authority names should use a Java-style naming convention (such as com.example.provider.cartoonprovider). Typically, it's the name of the ContentProvider subclass that implements the provider.

In your case, android:authorities should have the value: de.somename.provider.hvkContentProvider.


android:name:...... The name of the class that implements the content provider, a subclass of ContentProvider. This should be a fully qualified class name (such as, "com.example.project.TransportationProvider"). However, as a shorthand, if the first character of the name is a period, it is appended to the package name specified in the element.

So, if you are defining package in the manifest tag of AndroidManifest.xml, make sure hvkContentProvider is in that package. Else, change android:name=".hvkContentProvider" to android:name="de.somename.hvk3.hvkContentProvider" or your.package.name.hvkContentProvider

Colocynth answered 30/8, 2013 at 20:37 Comment(2)
You nudged me in the right direction...thank you. Your suggestions started bringing other Errors which ultimately lead me to solving the content provider problem. You did get me moving again though...Heyman
Say, why does the IDE warn about using android:exported="true" ? When I set it to false, it has issues with some apps when I choose to share multiple files...Temperate
H
4

Try using fully qualified path in android:authorities thereby replacing de.somename.provider with de.somename.provider.hvkContentProvider in so that it becomes as follows.

<provider android:authorities="de.somename.provider.hvkContentProvider"
              android:enabled="true"
              android:multiprocess="true"
              android:name=".hvkContentProvider"
              android:exported="true" ></provider>

You can refer this

Houlberg answered 30/8, 2013 at 10:47 Comment(0)
B
1

I faced the similar issue, and none of the solutions worked for me. Finally stumbled upon the below link(Failed to find Content Provider in API 30) and this solution worked like a magic. For the application with API above 29, declare the following block in your AppB menifest file

    <manifest>
...
    <queries>
        <provider android:authorities="com.example.appcontainprovider" />
    </queries>
...
</manifest>

where authorities value is provider authorities.

Bentinck answered 5/7, 2021 at 15:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.