偶发的IllegalArgumentException错误:未知的URL content://

5

很少出现:

Fatal Exception: java.lang.IllegalArgumentException: Unknown URL content://com.example.provider/info  
    at android.content.ContentResolver.insert(ContentResolver.java:1252)

Fatal Exception: java.lang.IllegalArgumentException: Unknown authority com.example.provider
    at android.content.ContentResolver.applyBatch(ContentResolver.java:1247)

强调一下很少。通常情况下,没有问题,所以授权设置正常,但偶尔会出现无法找到内容提供程序的情况。有什么原因导致ContentResolver无法找到ContentProvider吗(例如,如果尚未设置)?


你在manifest.xml中定义ContentProvider的authority和android:exported="true"属性是否一致? - Michele Lacorte
1
是的,在 AndroidManifest 和使用中,内容提供程序的权限是相同的,这已经通过测试正确解析内容 URI 证明。内容提供程序仅用于内部使用,因此我们的“exported”设置为 false。 - David Liu
你如何定义你的ContentProvider? - rds
你测试过 properly insert 和 apply_batch 了吗?发一下你的 content provider 代码,这样我们就可以看看它。 - jdesesquelles
1
@jdesequelles,contentProvider端的insert/apply_batch代码有点无关紧要,因为它甚至没有到达那段代码。这个崩溃是由于找不到内容提供程序,所以它无法将这些命令发送给它。尽管如上所述,插入和applyBatch在99%的情况下都可以正常工作。这是一个罕见的情况,我想修复它。 - David Liu
@DavidLiu,你最终做出了什么决定?你是如何解决这个问题的? - Rob
1个回答

5
我曾在自定义的Application对象中进行ContentResolver操作时,遇到了罕见的IllegalArgumentException和未知URI问题。
例如,在应用程序的onCreate方法中尝试删除内容提供程序中的项目,但偶尔会崩溃。
public class CustomApplication extends Application {

    @Override
    public void onCreate() {
        //..
        context.getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
        //.. 
    }
}

有时会导致以下崩溃:

Fatal Exception: java.lang.RuntimeException: Unable to create application com.myapp.CustomApplication: java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431)
   at android.app.ActivityThread.access$1800(ActivityThread.java:229)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:148)
   at android.app.ActivityThread.main(ActivityThread.java:7331)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
       at android.content.ContentResolver.delete(ContentResolver.java:1376)
       at com.myapp.ReminderEntryDao.delete(Unknown Source)
       at com.myapp.CustomApplication.onCreate(Unknown Source)
       at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037)
       at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6428)
       at android.app.ActivityThread.access$1800(ActivityThread.java:229)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:7331)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

我还看到了类似的行为,使用BOOT_COMPLETE接收器。每月活跃用户约20万人中,我有大约70个报告的崩溃异常(大多是Infinix设备约43%,几乎没有三星设备)。IllegalArguementException Device Stats 我将其移入后台计划任务,自那以后就没有再出现过崩溃。我只能在我用过但从未再次遇到的Nexus设备上重现此问题。
我怀疑在某些Android版本的某些设备上,Application/BOOT_COMPLETE接收器在ContentProvider完全初始化之前进行了初始化,因此当它尝试访问时,它尚未正确设置。
有一些stackoverflow帖子确实说明了首先创建什么以及操作系统应该如何行动: Is the Application class guaranteed to be instantiated before a defined boot receiver is called

但是,正如我所说的,我也看到了不同的情况,将操作从类中移动到后台调度程序似乎可以解决问题(也许只是因为设置需要更长时间)。希望我的经验能对您有所帮助。

编辑:我使用了 evernote工作调度器,如果需要,将我的ContentResolver操作推迟到了工作中。(但我认为将内容提供程序操作推迟到任何一种后台处理可能会修复它,因为它有更多的时间来设置 - 当然这只是我的猜测)。

class DeleteRemindersJob extends Job {
    @NonNull
    @Override
    protected Result onRunJob(final Params params) {
        cursor = getContext().getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
        //..
        return Result.SUCCESS;
    }
}

你能详细介绍一下后台定时任务吗?此外,你是否看到这种情况发生在更主流的设备上(例如摩托罗拉/三星等)? - David Liu
@DavidLiu 我已经更新了答案并提供了更多信息 - 总结一下,我在三星设备上没有真正看到过这个问题,但是在Nexus模拟器上却遇到了。我还使用了evernote作业调度程序在后台处理它,但我认为将其移动到任何后台操作中都会有帮助,例如IntentService或Service。 - riggaroo
我在一些设备上遇到了这个问题,包括三星设备。在我的情况下,ContentProvider 在后台线程中被访问,但是该线程可以非常早地启动。我阅读了关于这个答案的内容,并决定将该线程中的作业延迟 1 秒。但它并没有很好地工作,我仍然收到这些崩溃报告。我是否漏掉了什么? - hqzxzwb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接