Android duplicate provider authority problem

前端 未结 4 624
长情又很酷
长情又很酷 2021-01-05 07:08

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.

相关标签:
4条回答
  • 2021-01-05 07:34

    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

    0 讨论(0)
  • 2021-01-05 07:43

    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.

    0 讨论(0)
  • 2021-01-05 07:50

    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.

    0 讨论(0)
  • 2021-01-05 07:52

    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" }

    0 讨论(0)
提交回复
热议问题