Android重复提供者权限问题

发布于 2024-11-16 15:14:07 字数 489 浏览 1 评论 0原文

我们正在尝试发布一款休闲应用程序的付费无广告版本,该应用程序目前免费发布但带有广告。我们将所有包名重构为com.mycompanyname.appname.pro,市面上的免费包基本上没有.pro结尾。我们还进入了内容提供商并将权限更改为与包名称相同。因此,“免费版本”具有

AUTHORITY = "com.mycompanyname.appname" 

“无广告付费版本”

AUTHORITY = "com.mycompanyname.appname.pro" 

,但我们仍然无法在同一设备上安装免费版本和“专业”版本。无论它的价值如何,提供商的类名称是两个应用程序都是一样的。

我们无法直接从 apk 安装,如果我们尝试从 Android 市场下载,我们会收到“重复的提供商权限”错误消息,

我们还需要在其他地方查找问题吗? ,或者我们这里有什么根本性的错误吗?

We're trying to publish a pay ad-free version of a casual app that's currently published free with ads. We refactored all package names to com.mycompanyname.appname.pro, the free one on market doesn't have the .pro at the end, basically. We also went into our content provider and changed the authority to the same as the package name. So the "free version" has

AUTHORITY = "com.mycompanyname.appname" 

and the "ad-free pay version has

AUTHORITY = "com.mycompanyname.appname.pro" 

but still we are unable to install both the free and the "pro" version on the same device. For whatever it's worth, the class name for the provider is the same in both apps.

We can't install from an apk directly, and if we try to download from Android market we get a "duplicate provider authority" error message.

What are we missing? Is there another place we need to look for problems, or have we got something fundamentally wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝眸 2024-11-23 15:14:07

基本上我所做的是,为我的每个 ContentProvider 创建一个抽象基类,并为我想要制作的每个应用程序继承该抽象基类,覆盖权限路径。所以在我的 AbstractContentProvider 中我有:

public AbstractContentProvider() {
    sURIMatcher.addURI(getAuthority(), BASE_PATH, ITEMS);
    sURIMatcher.addURI(getAuthority(), BASE_PATH + "/#", ITEM_ID);
}

protected abstract String getAuthority();

然后在每个子类中我有:

private static final String AUTHORITY = "my.package.app1.ContentProvider";

@Override
protected String getAuthority() {
    return AUTHORITY;
}

在 AndroidManifest 中我注册了这些:

    <provider
          android:name="my.package.app1.ContentProvider"
          android:authorities="my.package.app1.ContentProvider">
    </provider>

现在的技巧是,我想在通用(库)代码中访问这些内容提供程序,它不知道应用程序具体课程。为此,我在 strings.xml 中定义了一个字符串,并为每个应用程序覆盖该字符串。然后我可以使用:

Uri.parse(getString(R.string.contentProviderUri))

并且在每个应用程序中都使用正确的ContentProvider,没有任何冲突。所以基本上都是使用配置机制来进行依赖注入。

Basically what I did is, create an abstract base class for each of my ContentProviders and inherit from that for each app I want to make, overriding the authority path. So in my AbstractContentProvider I have:

public AbstractContentProvider() {
    sURIMatcher.addURI(getAuthority(), BASE_PATH, ITEMS);
    sURIMatcher.addURI(getAuthority(), BASE_PATH + "/#", ITEM_ID);
}

protected abstract String getAuthority();

and then in each subclass I have:

private static final String AUTHORITY = "my.package.app1.ContentProvider";

@Override
protected String getAuthority() {
    return AUTHORITY;
}

In the AndroidManifest I register these with:

    <provider
          android:name="my.package.app1.ContentProvider"
          android:authorities="my.package.app1.ContentProvider">
    </provider>

Now the trick is, I want to access these content providers in common (library) code, that doesn't know about the app specific classes. To do that, I define a String in my strings.xml, that I override for each app. Then I can use:

Uri.parse(getString(R.string.contentProviderUri))

and in every app the right ContentProvider is used without any conflicts. So basically using the configuration mechanism for dependency injection.

╭⌒浅淡时光〆 2024-11-23 15:14:07

可以说你的
库包是com.android.app.library
免费包是com.android.app.free
付费包是com.android.app.paid

在你的免费项目和付费项目中,在一个包中创建一个相同的文件,可以是任何东西,但必须相同。

示例:

  1. 使用 com.android.app.data 在免费版本中创建新包

  2. 创建一个名为 Authority 的文件。 java 和里面(Authority.java)放:

    公共类权威{

    `public static final String CONTENT_AUTHORITY = "您的提供商";`
    

    }

  3. 对于付费版本重复此操作,记住保持包名称和类名称相同。

现在,在您的合同文件中,在您的库中使用以下内容:

public static String AUTHORITY = initAuthority();

    private static String initAuthority() {
        String authority = "something.went.wrong.if.this.is.used";

        try {

            ClassLoader loader = Contract.class.getClassLoader();

            Class<?> clz = loader.loadClass("com.android.app.data.Authority");
            Field declaredField = clz.getDeclaredField("CONTENT_AUTHORITY");

            authority = declaredField.get(null).toString();
        } catch (ClassNotFoundException e) {} 
        catch (NoSuchFieldException e) {} 
        catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }

        return authority;
    }

    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

现在您应该能够使用两个权限。

图片来源:伊恩·瓦里克
Android - 在应用项目中拥有提供商权限

Lets say your
library package is com.android.app.library
free package is com.android.app.free
paid package is com.android.app.paid

In your free project and paid project, make an identical file in a package which can be anything, but must be the same.

Example:

  1. Create a new package in your free version with com.android.app.data

  2. Create a file called Authority.java and inside (Authority.java) put:

    public class Authority {

    `public static final String CONTENT_AUTHORITY = "YOUR PROVIDER";`
    

    }

  3. Repeat this for the paid version, remember to keep the package name the same and class name.

Now, in your contract file, in your library use the following:

public static String AUTHORITY = initAuthority();

    private static String initAuthority() {
        String authority = "something.went.wrong.if.this.is.used";

        try {

            ClassLoader loader = Contract.class.getClassLoader();

            Class<?> clz = loader.loadClass("com.android.app.data.Authority");
            Field declaredField = clz.getDeclaredField("CONTENT_AUTHORITY");

            authority = declaredField.get(null).toString();
        } catch (ClassNotFoundException e) {} 
        catch (NoSuchFieldException e) {} 
        catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }

        return authority;
    }

    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

Now you should be able to use two authorities.

Credit: Ian Warick
Android - Having Provider authority in the app project

絕版丫頭 2024-11-23 15:14:07

默认情况下,Google 在您的 APP 中添加应用测量提供程序,因此在 build.gradle 文件中,您需要在 android 标签 exaple 下定义 applicationID
默认配置{
applicationId“com.example.my.app”
minSdkVersion 15
目标SDK版本19
版本代码1
版本名称“1.0”
}

Google by default add app measurement provider in your APP so in build.gradle file you need to define applicationID under android tag exaple
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}

陪你到最终 2024-11-23 15:14:07

我遇到了同样的问题,有一条错误消息抱怨提供者名称已被注册。我认为诀窍可能是使用不同的权限和不同的名称 - 因此,在我的例子中,从免费版和专业版的库项目中扩展我的基本提供程序。如果您仍然遇到这个问题,这将解决您的问题(注意到这是一篇旧帖子,但没有答案,所以我决定发布我解决它的方法)。

我很好奇是否有其他人遇到同样的事情,果然这似乎是 Android 平台中的一个错误。请参阅此处或类似的 SO 帖子此处

I was running into the same issue, with an error message complaining that the provider name was already registered. I thought the trick might be to use both a different authority as well as a different name--so, extending my base provider from the library project in both the free and pro versions, in my case. This will fix your issue, if you're still having it (noticed this was an old post, but no answers so I decided to post the way I got around it anyway).

I was curious if anyone else was running into the same thing, and sure enough it seems to be a bug in the Android platform. See the issue details here or a similar SO post here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文