14.12.2010 11:36, Mark Carter пишет:
I think there is a problem there because you are setting AUTHORITY from the constructor and so there is a chance it has not been set when Uri.ParseUri("content://" + CommonContentProviderBase.AUTHORITY.....) is called. It probably makes more sense for that static to be set as a final by using something like ANT as you mentioned.

Content providers are instantiated and registered before any Activity. You could also put code to set the static into Application subclass (different for lite/pro), to make it more explicit.


Also, what about my other apps (and 3rd party apps) that want to access the content provider? They need to use the appropriate content provider no matter whether lite, pro or both versions are installed.

Since you can't have two providers in the system that have the same authority URI, it probably means that some kind of client library for other applications is needed.

ContentResolver actually throws IllegalArgumentException if it can't match the URI to an existing content provider, you could leverage that to gracefully fail over from pro to lite version. Using queryContentProviders would also be appropriate here, IMHO.


I've been thinking about what I'm try to do and it's not a million miles away from something similar to QSB, so I feel that using a similar model to that is probably the most sensible approach.

One other thing that also needs to be considered: when the Lite version wants to use the content provider it's probably best it does not use the Pro version's (if the Pro version is also installed). Therefore there needs to be slightly different logic involved when accessing a ContentProvider within the app, as opposed to from another app.

On 14 December 2010 16:08, Kostya Vasilyev <[email protected] <mailto:[email protected]>> wrote:

    Mark,

    The way you're doing this seems waaay too complicated.

    The goal is to use common code for the content provider, while
    being able to switch the authority string and the class name, agreed?

    If you are building with ant, there is a task that does string
    replacements.

    If you are using Eclipse / library project, just create a subclass
    of the common content provider base class in each of the
    respective application projects. Use this subclass in the
    manifest, and have it pass the authority string to the base class,
    where it can be stored in a static, and used by the content
    provider's clients.

    Library:

    class CommonContentProviderBase extends ContentProvider {
    public static String AUTHORITY = null;

    CommonContentProviderBase (String authority) {
    AUTHORITY = authority;
    }

    @Override
    public boolean onCreate() {
    gUrlMatcher.addURI(AUTHORITY, ... );
    ...
    }
    ....
    }

    Use like this:

    Uri.ParseUri("content://" + CommonContentProviderBase.AUTHORITY.....)

    Lite application:

    class LiteProvider extends CommonContentProviderBase {
    public LiteProvider() {
    super("mark.carter.data.lite");
    }
    }

    <provider name=".LiteProvider" authorities="mark.carter.data.lite"/>

    Similar for the pro version.

    -- Kostya

    14.12.2010 7:17, Mark Carter пишет:

        An app cannot be installed if (in a provider Manifest element) it
        specifies an authority that has already been specified by an
        existing
        app.

        This can lead to problems when installing the pro version of
        an app
        with the lite version already installed.

        How do devs deal with this?

        My current approach is to always specify an authority using
        the app
        package name as a prefix. This guarantees uniqueness.

        Furthermore, I use a meta-data element to specify that the
        lite/pro
        content providers are logically the same.

        In the code, I use PackageManager.queryContentProviders() to
        get the
        authority "candidates" (sharing the same meta-data value) and then
        choose the most appropriate one to use in a Uri which I can
        then pass
        into ContentResolver.query().

        Essentially, I'm using the meta-data element to specify what I
        would
        like to use as an authority, but am prevented from doing so.

        This is quite cumbersome, so is there a neater way?



-- Kostya Vasilyev -- WiFi Manager + pretty widget --
    http://kmansoft.wordpress.com


-- You received this message because you are subscribed to the Google
    Groups "Android Developers" group.
    To post to this group, send email to
    [email protected]
    <mailto:[email protected]>
    To unsubscribe from this group, send email to
    [email protected]
    <mailto:android-developers%[email protected]>
    For more options, visit this group at
    http://groups.google.com/group/android-developers?hl=en


--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en


--
Kostya Vasilyev -- WiFi Manager + pretty widget -- http://kmansoft.wordpress.com

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to