0

I am attempting to white label my app by changing my Android Application Project into an Android Library Project and then importing the library into a new Android Application Project.

I am running into a problem with the fact that my app (read: Library Project) contains a ContentProvider.

When I attempt to install my new Android Application Project onto an emulator, console tells me:

[2014-01-24 13:35:39 - WhitelabelTest] Installation error: INSTALL_FAILED_CONFLICTING_PROVIDER
[2014-01-24 13:35:39 - WhitelabelTest] Please check logcat output for more details.
[2014-01-24 13:35:39 - WhitelabelTest] Launch canceled!

According to the logcat:

01-24 13:38:52.217: W/PackageManager(58): Can't install because provider name com.myapp.app.db.providers.MyProvider (in package com.example.whitelabeltest) is already used by com.myapp.app
01-24 13:38:52.227: W/PackageManager(58): Package couldn't be installed in /data/app/com.example.whitelabeltest-2.apk

Does this simply mean you cannot have both applications installed on the same device because they use the same ContentProvider? Or is there a way around this? Do I need to create a new ContentProvider in my new Android Project with a new name instead?

Here is the Provider as listed in my WhitelabelTest project's Manifest:

<provider
            android:name="com.myapp.app.db.providers.MessagesProvider"
            android:authorities="com.myapp.app.db.providers.MessagesProvider"
            android:exported="false" />

I attempted to change the name parameter with the same result.

Andrew
  • 20,756
  • 32
  • 99
  • 177

1 Answers1

1

Does this simply mean you cannot have both applications installed on the same device because they use the same ContentProvider?

You cannot have both applications installed on the same device because they both attempt to declare the same authority (in android:authorities) in a <provider>. There can only be one provider for a given authority.

This is similar to how you cannot have two apps installed with the same package.

Do I need to create a new ContentProvider in my new Android Project with a new name instead?

I'd start by considering whether a ContentProvider is necessary, and perhaps drop it if it is not.

Otherwise, the implementation of the ContentProvider can be the common one from the library project. However, the android:authorities must be unique, and therefore any clients of that ContentProvider need to know the right authority to use to reach the right provider.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I'm going to tear out the `ContentProvider` stuff. I do have a question. Is it better to instantiate and close my `SQLiteDatabaseHelper` and `SQLiteDatabase` in an `Activity`'s `onResume` and `onPause`? Or should I do it on an as-needed basis? – Andrew Jan 24 '14 at 21:25
  • Along the same vein, would I even need to keep an `SQLiteDatabase` member variable in my activity? Or is `mHelper.getWritableDatabase()` lightweight enough that I only need to instantiate an `SQLiteDatabaseHelper` instance? – Andrew Jan 24 '14 at 21:29
  • @AndrewL "Is it better..." -- if you will be accessing the database across multiple threads or multiple components, your `SQLiteOpenHelper` should be a singleton that lives the life of your process. "Or is mHelper.getWritableDatabase() lightweight enough that I only need to instantiate an SQLiteDatabaseHelper instance?" -- yes, `getReadableDatabase()`/`getWritableDatabase()` are cheap, except the very first time you open them *and* your helper's `onCreate()` or `onUpgrade()` need to be called. That's why you need to use those methods in a background thread, along with the rest of your I/O. – CommonsWare Jan 24 '14 at 22:21
  • I have already extended the Application class. Should I put it in there? If so, when will the `SQLiteDatabaseHelper` ever get closed? I suppose in `onTerminate()`? – Andrew Jan 24 '14 at 22:41
  • @Andrew: "Should I put it in there?" -- there's no particular value in doing that over just a static data member. But, you are welcome to do so if you want. "If so, when will the SQLiteDatabaseHelper ever get closed?" -- never, just like it is never getting closed in your `ContentProvider`. "I suppose in onTerminate()?" -- despite the existence of that callback, it is never called. – CommonsWare Jan 24 '14 at 23:08
  • Quick question about memory leaks: Is it ok to call `getApplicationContext()` within an `AsyncTask`? Or will this cause my `Activity` to leak until the `AsyncTask` is finished running? Would it be better to just pass the `Context` in? I realize I'm asking for the application's `Context`, but I don't know if the mechanism for retrieving it is through the `Activity`. Thanks for your help. – Andrew Feb 03 '14 at 19:38
  • @Andrew: Probably calling `getApplicationContext()` will be OK in `doInBackground()`, but I would still recommend passing in the `Application` in the `AsyncTask`'s constructor, just to be safe. – CommonsWare Feb 03 '14 at 19:44
  • So by using a static data member, do you mean just calling `DbHelper.getInstance(getApplicationContext()).getWritableDatabase()` everywhere in my code a database is needed (and passing a `Context` to any object that needs it but doesn't have access to the `getApplicationContext()` call)? – Andrew Feb 03 '14 at 20:22