腾讯 移动开发者接入指南
接入指南
加入 QQJSSDK.framework ,其中包含了 JS API 的插件管理器方法。下载所需 js 文件 包括:jsbridge.js。 cdn
备注
jsbridge.js : 白名单内的为可以走sdk.js中的mqq.invoke逻辑;
如果不在白名单,走老逻辑QZAppExternal;
[最终协议格式为](jsbridge://namespace/method?param=test¶m2=xxx¶m3=yyy#123)
android 开发指引
导入 SDK : 导入开发工具包 QQJsSdkQB.jar(若项目已经引入 TBS,请引入 TBSQQJsSDK.jar
备注
SDK中包含:
- 插件基类WebViewPlugin
- 插件引擎WebViewPluginEngine
- 引擎内的插件容器及插件配置WebViewPluginContainer与WebViewPluginConfig
自定义插件 : 继承类 WebViewPlugin
类 WebViewPlugin 说明:
public DefaultPluginRuntime mRuntime;//插件的运行时对象, 可以获取当前context、Activity、WebView等实例
protected void onCreate(){} // 插件创建时被调用, 可以重载做插件的初始化工作, 建议不要放太多的逻辑, 一些不常用的数据可以放到首次使用时初始化.
protected void onDestroy(){} //插件销毁时被调用, 可以重载做插件的回收工作.
/**
Webview里有JS调用会执行这个方法, 重载以实现自己的API
@param url 触发接口的jsbridge伪协议
@param pkgName 接口的包名
@param method 方法名
@param args[] 参数
@return 根据pkgName和method判断是否处理, true表示已处理, API调用结束, false表示未处理, API调用会继续传给下一个插件处理.
*/
protected boolean handleJsRequest(String url, String pkgName, String method, String... args) {..}
public void onActivityResult(Intent intent, byte requestCode, int resultCode){}//启动activity
public void startActivityForResult(Intent intent, byte requestCode){}//获取来自activity的result
public void callJs(String func, JSONObject data){}//用于回传数据给web端,参见getResult
Example:ShortcutPlugin
@Override
protected boolean handleJsRequest(String url, String pkgName, String method, String... args) {
if ("addShortcut".equals(method)) {
try {
JSONObject json = new JSONObject(args[0]);
//成功、失败回调
callback = json.optString(KEY_CALLBACK);
Shortcut shortcut = new Shortcut();
shortcut.setScheme(json.optString("scheme"));
shortcut.setTitle(json.optString("title"));
shortcut.setIcon(json.optString("icon"));
doAddShortcut(shortcut);//内部逻辑
} catch (JSONException e) {
e.printStackTrace();
}
}
return super.handleJsRequest(url, pkgName, method, args);
}
调用插件引擎 :
- 在 layout 和 ava 代码中使用 CustomWebView 代替系统的 WebView 类
- 参考如下 onCreate 初始化,其中 AuthorizeConfig 用于权限控制,需要继承实现调用插件引擎的 insertPlugin 方法将所需插件 list 注册到插件引擎的插件容器中
- 实现 WebViewPluginContainer 接口,在 pluginStartActivityForResult 和 onActivityResult 实现 result 的派发
- 在 onResume/onPause/onDestory 中加入相应的解决内存泄漏的代码
Example :
import com.tencent.mobileqq.webviewplugin.*;// import webviewplugin 的所有类
public class MyActivity extends Activity implements WebViewPluginContainer{// 声明实现 WebViewPluginContainer
CustomWebView webview;
protected WebViewPluginEngine mPluginEngine;
private PluginInfo[] pluginInfos= {new PluginInfo(ShareApiPlugin.class,"share", "mqq.share.* API", "1.0")};
protected void onCreate(Bundle savedInstanceState) {
webview=(CustomWebView) this.findViewById(R.id.webview);
mPluginEngine = new WebViewPluginEngine(WebViewPluginConfig.list,new DefaultPluginRuntime(webview,this));// 设置 common API
mPluginEngine.insertPlugin(pluginInfos);// 将插件添加入引擎中,pluginInfos为插件list
webview.setWebViewClient(new CustomWebViewClient(mPluginEngine));// 监听WebView
webview.setWebChromeClient(new CustomWebChromeClient(mPluginEngine));
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setUserAgentString("QQJSSDK/1.0.0 Android");
AuthorizeConfig.setClass(com.example.demo.QQAuthorizeConfig.class);// 设置 API 的权限配置
}
@Override
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= 11) {
webview.onResume();
} else {
}
}
@Override
protected void onPause() {
super.onPause();
if (Build.VERSION.SDK_INT >= 11) {
webview.onPause();
} else {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mPluginEngine.onDestroy(); //重要, 一定要加, 防止内存泄露
webview.destroy();
}
@Override
public int pluginStartActivityForResult(WebViewPlugin plugin, Intent intent, byte requestCode) {
return WebViewPlugin.defaultPluginStartActivityForResult(this, plugin, intent, requestCode);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (WebViewPlugin.defaultPluginOnActivityResult(mPluginEngine, requestCode, resultCode, data)) {
return;
}
}
}
分发请求 : 调用插件引擎的 handleJsRequest 将请求分发给对应的插件。
iOS 开发指引
引入自定义 UI 控制类 :引入自己的 UIViewController 类,在该类类别中遵循 AppWebViewProtocol 协议,并实现协议方法
@interface AppWebViewController : UIViewController
@end
@interface AppWebViewController(JSAPI) <AppWebViewProtocol>
-(NSURL*)getPageURL;
-(NSString *)executeJsScript:(NSString*)script;
@end
嵌入 Webview :在自己的 UIViewController 中嵌入 UIWebview,并按照正常的 UIWebview 加载方法进行加载,并且必须实现 UIWebViewDelegate 中的如下方法
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//把请求交给webview插件管理器处理,以后所有schema请求都放这里面注册成插件来处理
if ([[QQJSWebViewPluginEngine getInstance] handleSchemaRequest:request.URL fromWebview:self]) {
return NO;
}
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventLoadStart userInfo:nil fromWebview:self];
//TO DO ....
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventLoadFinish userInfo:nil fromWebview:self];
//TO DO ....
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventLoadFail userInfo:@{@"error":error} fromWebview:self];
//TO DO ....
}
插件进行事件处理 : 在 UIViewController 的生命周期方法中让插件进行事件处理
-(void)viewWillAppear:(BOOL)animated {
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventWillAppear userInfo:nil fromWebview:self];
//TO DO ....
}
- (void)viewDidAppear:(BOOL)animated{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventDidAppear userInfo:nil fromWebview:self];
//TO DO ....
}
- (void)viewWillDisappear:(BOOL)animated{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWebViewEventWillDisappear userInfo:nil fromWebview:self];
//TO DO ....
}
- (void)viewDidDisappear:(BOOL)animated{
//TO DO ....
[[QQWebViewPluginEngine getInstance] handleEvent:QQWEbViewEventDidDisappear userInfo:nil fromWebview:self];
//页面被销毁时插件也要销毁
if([self isOrphan:self])
{
[[QQWebViewPluginEngine getInstance] handleWebviewDestory:self];
}
//TO DO ....
}
- (BOOL)isOrphan:(UIViewController *)viewController{
if (viewController) {
if (viewController.parentViewController && [viewController.parentViewController isKindOfClass:[UINavigationController class]]) {
//如果viewController是放在navigationController里的,我们应该判断该navigationController
return [self isOrphan:viewController.navigationController];
}
else {
//否则直接判断,如果viewController又没parent又没被present,则返回YES
return !viewController.parentViewController && !viewController.presentingViewController;
}
}
return YES;
}
view 的生命周期方法需按照上面的实现方法进行,绿色 TODO 部分可用来写入其他处理,完成上面步骤即可开始调用 JS API
建立自己的插件类 : 建立自己的插件类,并继承 QQJSBridgePluginHelper
#import <Foundation/Foundation.h>
#import "QQJSBridgePluginHelper.h"
@interface QQJSBridgeDemoPlugin : QQJSBridgePluginHelper
@end
注册插件 : 在 QQWebViewPluginConfigs.h 中注册该插件,其中 func 字段的值是插件的模块名
@"com.tencent.sng.app.jsbridge.device": @{
@"cls": [QQJSBridgeDemoPlugin class],
@"desc": @"JSBridge Demo Module Plugin",
@"ver": @"1.0.0",
@"func": @[@"device"]
},
实现自定义插件方法并命名 : 在该类中实现自己的插件方法按照 handleJsBridgeRequest 模块名方法名的格式来命名插件方法
#import "QQJSBridgeDemoPlugin.h"
@implementation QQJSBridgeDemoPlugin
#pragma mark - mqq.offline
#define kJsCallback @"callback"
#define kJS_NULL_STR @"null"
#define kSyncCallTimeout dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC)
#define kAsyncCallTimeout DISPATCH_TIME_FOREVER
-(id)init
{
self = [super init];
if (self) {
}
return self;
}
- (id)handleJsBridgeRequest_device_isMobileQQ:(NSDictionary*)params
{
NSLog(@"handleJsBridgeRequest_device_isMobileQQ");
return nil;
}
//旧接口:执行更新并返回更新结果
- (id)handleJsBridgeRequest_offline_update:(NSDictionary*)params
{
//业务BID
NSString *bid = [NSString stringWithFormat:@"%@", [params objectForKey:@"bid"]];
NSString *updateJsCallback = [params objectForKey:kJsCallback];
//防止参数为空
if (!updateJsCallback || !bid)
{
[self evaluateOfflineJavascript:updateJsCallback event:0 ret:0 response:nil];
return nil;
}
//通知JS:event为0,代表本地是否缓存
[self evaluateOfflineJavascript:updateJsCallback event:0 ret:0 response:nil];
return nil;
}
- (void)evaluateOfflineJavascript:(NSString*)callback event:(int)event ret:(int)ret response:(NSString*)response
{
//需要执行的JS脚本
NSString *script = [NSString stringWithFormat:@"%@(%d, %d, %@)", callback, event, ret, response ? response : kJS_NULL_STR];
[self evaluateOfflineJavascript:script];
}
- (void)evaluateOfflineJavascript:(NSString*)script
{
if ([NSThread isMainThread])
{
[self.webViewController executeJsScript:script];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.webViewController executeJsScript:script];
});
}
}
@end
开发者规范
综述 : 开发者开发时,除了需要满足每个接口的规范限制、调用频率限制外,还需特别注意模版消息、用户数据等敏感信息的使用规范。
涉及用户数据时
您的服务需要收集用户任何数据的,必须事先获得用户的明确同意,且仅应当收集为运营及功能实现目的而必要的用户数据, 同时应当告知用户相关数据收集的目的、范围及使用方式等,保障用户知情权。 您收集用户的数据后,必须采取必要的保护措施,防止用户数据被盗、泄漏等。 如果腾讯认为您收集、使用用户数据的方式,可能损害用户体验,腾讯有权要求您删除相关数据并不得再以该方式收集、使用用户数据。 一旦您停止使用本服务,或腾讯基于任何原因终止您使用本服务,您必须立即删除全部因使用本服务而获得的数据(包括各种备份), 且不得再以任何方式进行使用。
其他规范
请勿设置或发布任何违反相关法规、公序良俗、社会公德等的玩法、内容等。 请勿公开表达或暗示,您与腾讯之间存在合作关系,包括但不限于相互持股、商业往来或合作关系等,或声称腾讯对您的认可。 完整的开发者规范和接口限制,请详见开发者接口文档
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Python 知识点总结
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论