不少关于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