是否需要覆盖ContentProvider的getType方法?

是否需要覆盖ContentProvider的getType方法?

      不少关于android的书籍都谈到了ContentProvider,而且给了例子,但是对ContentProvider的getType方法则是寥寥数语带过,以至于读者对其作用始终有种雾里看花的感觉。本文从一个侧面谈谈getType的作用,希望对大家有所帮助。本文不再另写例子程序,具体例子可以参考android自带的sample程序notepad。

       在notepad app中大家可以看到NotePadProvider覆盖了getType方法,让其返回相应的类型。那么他的作用是什么呢?让我们来看看吧!

       首先,改写NotePadProvider的getType方法,让其返回null;然后编译后启动,按下menu key,出现含有add note的menu,点击之。哦哦!出错了,提示“android.content.ActivityNotFoundException: No Activity found to handle Intent”!为什么呢?

       且听我从头道来。

      首先,大家知道android app的安装是由PM(package manager)负责的,在安装android app时,PM将app中的activities,services,broadcasts和content providers记录下来且为他们建立相应的intent filter,以便后面启动他们时使用。关于intent filter的建立,大家可以参见IntentResolver.java文件的addFilter函数,从此处可以看到它建立了关于scheme,type,action和typedAction的列表。

      其次,在点击add note菜单项后,notepad app的处理是startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));对应framework的处理是instrumentation.java中的execStartActivity,在其中,大家可以看到 

          int result = ActivityManagerNative.getDefault()

                .startActivity(whoThread, intent,

                        intent.resolveTypeIfNeeded(who.getContentResolver()),

                        null, 0, token, target != null ? target.mEmbeddedID : null,

                        requestCode, false, false);

哦哦!这里有对intent.resolveTypeIfNeeded(who.getContentResolver())的调用,具体过程不再详述,大家有兴趣的话,可以参考intent.java,代码还是比较简单的。该函数的作用是返回intent对应的MIME type,这个MIME type就是通过调用NotePadProvider的getType方法得来的。

        接着来,下面framework将继续调用ActivityManagerService.java中的

startActivity –> startActivityMayWait,这里有很重要的一行代码:

            ResolveInfo rInfo =

                ActivityThread.getPackageManager().resolveIntent(

                        intent, resolvedType,

                        PackageManager.MATCH_DEFAULT_ONLY

                        | STOCK_PM_FLAGS);

这里就用到了上面PM建立的scheme,type,action和typedAction的列表,由于我们修改了NotePadProvider的getType方法,让其返回null,所以这里参数resolvedType值为null,以至于PM无法为其找到匹配的ResolverInfo,那么下面的代码:

        if (aInfo != null) {

            // Store the found target back into the intent, because now that

            // we have it we never want to do this again.  For example, if the

            // user navigates back to this point in the history, we should

            // always restart the exact same activity.

            intent.setComponent(new ComponentName(

                    aInfo.applicationInfo.packageName, aInfo.name));

 

            // Don't debug things in the system process

            if (debug) {

                if (!aInfo.processName.equals("system")) {

                    setDebugApp(aInfo.processName, true, false);

                }

            }

        }

将无法执行,所以intent不能设置与其相应的Component(也就是和intent相关的activity的信息),因此“android.content.ActivityNotFoundException: No Activity found to handle Intent”出现了!

      结论:覆盖ContentProvider的getType方法对于用new Intent(String action, Uri uri)方法启动activity是很重要的,如果它返回的MIME type和activity在<intent filter>中定义的data的MIME type不一致,将造成activity无法启动。

来源:http://blog.csdn.net/imyfriend/article/details/6589917

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值