曾经有一位心目中的大牛说过一句话,chromium中有很多很多的新技术。这些让你非常的着迷,而现在android kitkat的面试,会将这些新技术让更多的人去了解。
今天,就将去研究一下kitkat的browser关于jni的调用。
首先在4.4之前的版本上面,jni的调用一般是这样实现的。
在java端:
声明一个native函数
private native void nativeLoadUrl(String url, Map<String, String> headers);
使用的时候:
public void loadUrl(String url, Map<String, String> extraHeaders) {
mLoadInitFromJava = true;
if (URLUtil.isJavaScriptUrl(url)) {
// strip off the scheme and evaluate the string
stringByEvaluatingJavaScriptFromString(
url.substring("javascript:".length()));
} else {
nativeLoadUrl(url, extraHeaders);
}
mLoadInitFromJava = false;
}
而在cpp端,会有一个native method数组,比如
static JNINativeMethod gBrowserFrameNativeMethods[] = {
/* name, signature, funcPtr */
{ "nativeCallPolicyFunction", "(II)V",
(void*) CallPolicyFunction },
{ "nativeCreateFrame", "(Landroid/webkit/WebViewCore;Landroid/content/res/AssetManager;Landroid/webkit/WebBackForwardList;)V",
(void*) CreateFrame },
{ "nativeDestroyFrame", "()V",
(void*) DestroyFrame },
{ "nativeStopLoading", "()V",
(void*) StopLoading },
{ "nativeLoadUrl", "(Ljava/lang/String;Ljava/util/Map;)V",
(void*) LoadUrl },
然后就可以找到这个函数的具体实现:
static void LoadUrl(JNIEnv *env, jobject obj, jstring url, jobject headers)
但是现在的kitkat中,因为是使用的chromium的引擎。所以流程发生了一些改变:
java端:
public void loadUrl(LoadUrlParams params) {
if (mNativeContentViewCore == 0) return;
nativeLoadUrl(mNativeContentViewCore,
params.mUrl,
params.mLoadUrlType,
params.mTransitionType,
params.mUaOverrideOption,
params.getExtraHeadersString(),
params.mPostData,
params.mBaseUrlForDataUrl,
params.mVirtualUrlForDataUrl,
params.mCanLoadLocalResources);
}
在cpp端的h文件中,会直接继承并声明
class ContentViewCoreImpl : public ContentViewCore,
public NotificationObserver {
然后函数会用Jni的参数来进行声明:
void LoadUrl(
JNIEnv* env, jobject obj,
jstring url,
jint load_url_type,
jint transition_type,
jint ua_override_option,
jstring extra_headers,
jbyteArray post_data,
jstring base_url_for_data_url,
jstring virtual_url_for_data_url,
jboolean can_load_local_resources);
这样就省却了声明native method的操作。
再往下面就是函数的实现了:
void ContentViewCoreImpl::LoadUrl(
JNIEnv* env, jobject obj,
jstring url,
jint load_url_type,
jint transition_type,
jint ua_override_option,
jstring extra_headers,
jbyteArray post_data,
jstring base_url_for_data_url,
jstring virtual_url_for_data_url,
jboolean can_load_local_resources) {
DCHECK(url);
NavigationController::LoadURLParams params(
GURL(ConvertJavaStringToUTF8(env, url)));
params.load_type = static_cast<NavigationController::LoadURLType>(
load_url_type);
params.transition_type = PageTransitionFromInt(transition_type);
params.override_user_agent =
static_cast<NavigationController::UserAgentOverrideOption>(
ua_override_option);
if (extra_headers)
params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
if (post_data) {
std::vector<uint8> http_body_vector;
base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
params.browser_initiated_post_data =
base::RefCountedBytes::TakeVector(&http_body_vector);
}
if (base_url_for_data_url) {
params.base_url_for_data_url =
GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
}
if (virtual_url_for_data_url) {
params.virtual_url_for_data_url =
GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
}
params.can_load_local_resources = can_load_local_resources;
LoadUrl(params);
}
这下应该就是一个完整的jni调用了 ~~~