几年前使用Cordova 进行两个app之间的相互调用和通信;当时也是几经折腾,今天把它整理出来,理一下思路,也方便有一样需求的朋友参考java
require("cordova!com.lampa.startapp-master");
这个插件下载 https://github.com/dengxiaoning/com.lampa.startapp
(申明:该插件参考https://github.com/lampaa/com.lampa.startapp本身实现了ios的参数传递以及 downloadApps
应用下载的功能)android
首选来看看这个插件的实现ios
<js-module src="www/startApp.js" name="startapp"> <merges target="startApp" /> </js-module>
指定了js module 的路径和调用时的名称target="startApp"
git
<!-- android --> <platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> <feature name="startApp"> <param name="android-package" value="com.lampa.startapp.startApp"/> </feature> </config-file> <source-file src="src/android/startApp.java" target-dir="src/com/lampa/startapp" /> </platform> <platform name="ios"> <config-file target="config.xml" parent="/*"> <feature name="startApp"> <param name="ios-package" value="startApp"/> </feature> </config-file> <header-file src="src/ios/startApp.h"/> <source-file src="src/ios/startApp.m"/> </platform>
指定插件源文件路径,根据不一样平台,定义插件包名、将文件写入平台指定的路径下github
var exec = require('cordova/exec'); module.exports = { set: function(params, extra) { var output = [params]; if(extra != undefined) { output.push(extra); } else { output.push(null); } return { start: function(completeCallback, errorCallback) { completeCallback = completeCallback || function() {}; errorCallback = errorCallback || function() {}; exec(completeCallback, errorCallback, "startApp", "start", output); }, }, /** * extra values */ getExtras: function(completeCallback, errorCallback) { exec(completeCallback, errorCallback, "startApp", "getExtras", []); }, }
该js 实现了使用Cordova 调用android 和 ios 原生接口而后返回参数,
如:exec(completeCallback, errorCallback, "startApp", "start", output);
其中startApp
指定调用的类名
【ios是@interface startApp : CDVPlugin
,android是public class startApp extends CordovaPlugin
】;
start
指定调用该类的方法名;其余参数就是cordova 导出的成功、错误回调和携带返回数据。web
/** * download application from market * */ public void downloadApps(JSONArray args, CallbackContext callback){ JSONObject params; try { if(args.get(0) instanceof JSONObject){ params = args.getJSONObject(0); if(params.has("application")) { Uri uri = Uri.parse("market://details?id="+params.getString("application")+""); Intent it = new Intent(Intent.ACTION_VIEW, uri); cordova.getActivity().startActivity(it); } if(params.has("downloadurl")){ cordova.getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(params.getString("downloadurl")))); } } } catch (JSONException e) { callback.error("JSONException: " + e.getMessage()); e.printStackTrace(); } catch (ActivityNotFoundException e) { callback.error("ActivityNotFoundException: " + e.getMessage()); e.printStackTrace(); } }
增长Android 根据路径下载apk的方法
shell
- (void)getExtras:(CDVInvokedUrlCommand*)command; - (void)downloadApps:(CDVInvokedUrlCommand*)command; - (void)exitApplication:(CDVInvokedUrlCommand*)command;
增长ISO平台下 获取应用调用时传入的参数,在未安装时根据url下载应用
apache
- (void)getExtras:(CDVInvokedUrlCommand*)command{ CDVPluginResult* pluginResult = nil; // 从 url中获取保存的参数,将其返回给Cordova NSString *userurl = [[NSUserDefaults standardUserDefaults] objectForKey:@"url"]; if(userurl == nil || userurl == NULL){ NSString *addResult = @"returnFalse"; pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:addResult]; }else{ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:userurl]; [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"url"]; } [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } -(void)downloadApps:(CDVInvokedUrlCommand*)command{ CDVPluginResult* pluginResult = nil; NSString* scheme = [command.arguments objectAtIndex:0]; if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:scheme]]; pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:(true)]; } else { pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsBool:(false)]; } [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } - (void)exitApplication:(CDVInvokedUrlCommand*)command { exit(0); }
首先将该ios文件导入xcode,点击.xcodeproj后缀的文件,xcode将会自动打开,再找到 LSApplicationQueriesScheme 为应用添加容许访问的app的白名单。 而后添加Scheme(只有这样另外一个app在添加白名单时才知道写什么)。具体操做以下图json
![]() |
![]() |
![]() |
![]() |
同时配置ios访问设备的一些权限,不然无权限访问时应用会崩溃
找到 你的项目名-info.plist
文件打开,在最后一个array标签下加入配置xcode
<!-- 相册 --> <key>NSPhotoLibraryUsageDescription</key> <string>App须要您的赞成,才能访问相册</string> <!-- 相机 --> <key>NSCameraUsageDescription</key> <string>App须要您的赞成,才能访问相机</string> <!-- 麦克风 --> <key>NSMicrophoneUsageDescription</key> <string>App须要您的赞成,才能访问麦克风</string> <!-- 位置 --> <key>NSLocationUsageDescription</key> <string>App须要您的赞成,才能访问位置</string> <!-- 在使用期间访问位置 --> <key>NSLocationWhenInUseUsageDescription</key> <string>App须要您的赞成,才能在使用期间访问位置</string> <!-- 始终访问位置 --> <key>NSLocationAlwaysUsageDescription</key> <string>App须要您的赞成,才能始终访问位置</string> <!-- 日历 --> <key>NSCalendarsUsageDescription</key> <string>App须要您的赞成,才能访问日历</string> <!-- 提醒事项 --> <key>NSRemindersUsageDescription</key> <string>App须要您的赞成,才能访问提醒事项</string> <!-- 运动与健身 --> <key>NSMotionUsageDescription</key> <string>App须要您的赞成,才能访问运动与健身</string> <!-- 健康更新 --> <key>NSHealthUpdateUsageDescription</key> <string>App须要您的赞成,才能访问健康更新 </string> <!-- 健康分享 --> <key>NSHealthShareUsageDescription</key> <string>App须要您的赞成,才能访问健康分享</string> <!-- 蓝牙 --> <key>NSBluetoothPeripheralUsageDescription</key> <string>App须要您的赞成,才能访问蓝牙</string> <!-- 媒体资料库 --> <key>NSAppleMusicUsageDescription</key> <string>App须要您的赞成,才能访问媒体资料库</string>
操做截图
![]() |
![]() |
本身写的一个配置ios 相关权限和Scheme的xml
建立如上相似文件夹考入便可:
<?xml version="1.0" encoding="UTF-8"?> <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-plistconfig" version="5.3.0"> <name>开启第三方应用</name> <description>新开启第三方应用相关配置</description> <license>MIT</license> <keywords>cordova,sina</keywords> <!--require cordova version --> <engines> <engine name="cordova" version=">=3.5.0" /> </engines> <!-- ios --> <platform name="ios"> <!-- 容许访问的应用的 Scheme白名单,如打包A应用;此处应写B应用的scheme,(假如 将A定义为 aapp B定义为bapp 配置以下)。 反之打包的是B应用下面的配置就要反过来写了 --> <config-file platform="ios" target="*-Info.plist" parent="LSApplicationQueriesSchemes"> <array> <string>bapp</string> </array> </config-file> <!-- 当前应用本身的 Scheme --> <config-file platform="ios" target="*-Info.plist" parent="CFBundleURLTypes"> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLSchemes</key> <array> <string>aapp</string> </array> </dict> </array> </config-file> <!-- 配置相关权限 --> <config-file platform="ios" target="*-Info.plist" parent="NSAppleMusicUsageDescription"> <string>App须要您的赞成,才能访问媒体资料库</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSBluetoothPeripheralUsageDescription"> <string>App须要您的赞成,才能访问蓝牙</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSCalendarsUsageDescription"> <string>App须要您的赞成,才能访问日历</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSCameraUsageDescription"> <string>App须要您的赞成,才能访问相机</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSHealthShareUsageDescription"> <string>App须要您的赞成,才能访问健康分享</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSHealthUpdateUsageDescription"> <string>App须要您的赞成,才能访问健康更新 </string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSLocationAlwaysUsageDescription"> <string>App须要您的赞成,才能始终访问位置</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSLocationUsageDescription"> <string>App须要您的赞成,才能访问位置</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription"> <string>App须要您的赞成,才能在使用期间访问位置</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSMainNibFile"> <string></string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSMainNibFile~ipad"> <string></string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSMicrophoneUsageDescription"> <string>App须要您的赞成,才能访问麦克风</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSMotionUsageDescription"> <string>App须要您的赞成,才能访问运动与健身</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSPhotoLibraryUsageDescription"> <string>App须要您的赞成,才能访问相册</string> </config-file> <config-file platform="ios" target="*-Info.plist" parent="NSRemindersUsageDescription"> <string>App须要您的赞成,才能访问提醒事项</string> </config-file> </platform> </plugin>
// 在该方法中新增以下代码 - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation{ NSString *URLString= [url absoluteString]; [[NSUserDefaults standardUserDefaults] setObject:URLString forKey:@"url"]; [[NSUserDefaults standardUserDefaults] synchronize]; }
操做截图
A应用调用B应用的方法
invokeBapp(){ var sApp; sApp = startApp.set({// 设置应用包名----注意修改----该包名对应【被叫application】 "application" : "com.myapplication.bapp"// 替换为你真实的包名 }, {//传递给B应用的参数 "username" : "lili" "userId" : "123456" }); /* * 监测应用是否安装 */ cordova.plugins.fileOpener2.appIsInstalled(packageName, { success : function(res) { if (res.status === 0) { startApp.downloadApps({ "downloadurl":“https://192.168.1.1:8080/bapp/bapp.apk” //替换为你服务器真实的apk路径 },function(success){ console.log("success"); },function(error){ alert(error); }); } else { sApp.start(function(success) { // success console.log("OK"); }, function(error) { // fail alert(error); }); } } }); }
A应用调用B应用的方法
invokeBapp(){ var sApp; var sendParams = "username:lili;userId:123456"; //传递给B应用的参数(ios不能传递json对象) var twitter = “bapp://”; // B应用的Scheme(就是上面 第三 步配置的那个 再加上冒号和双斜杠就ok了) sApp = startApp.set(twitter + sendParams + ""); /* 监测是否安装应用 */ sApp.check(function(values) { sApp.start(function(success) { // success }, function(error) { // fail alert(error); }); }, function(error) { startApp.downloadApps({ "downloadurl":"itms-services:///?action=download-manifest&url=https://192.168.1.1:8080/bapp/dependence.plist" //替换为你服务器真实的plis路径(这里使用的是plist进行ipa下载,若是你已经发布到AppStore那就直接写AppStore下载路径了) }); }
receiveAappParams(){ startApp.getExtras(function(res){ // to do something... console.log(res); }); }
因为没u有上传到商店,ipa没法在ios应用中下载,全部使用plis进行ipa映射,而后调用Safari进行下载安装
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>items</key> <array> <dict> <key>assets</key> <array> <dict> <key>kind</key> <string>software-package</string> <key>url</key> <!-- ipa位于服务器的真实路径 --> <string>https://192.168.1.1:8080/bapp/bapp.ipa</string> </dict> <dict> <key>kind</key> <string>full-size-image</string> <key>needs-shine</key> <true/> <key>url</key> <!-- app下载时显示的图标 --> <string>https://192.168.1.1:8080/bapp/icon.png</string> </dict> <dict> <key>kind</key> <string>display-image</string> <key>needs-shine</key> <true/> <key>url</key> <!-- app下载时显示的图标 --> <string>https://192.168.1.1:8080/bapp/icon.png</string> </dict> </array> <key>metadata</key> <dict> <key>bundle-identifier</key> <!-- app包名 --> <string>com.myapplication.bapp</string> <key>bundle-version</key> <!-- app当前版本 --> <string>1.0.0</string> <key>kind</key> <string>software</string> <key>title</key> <!-- app名称 --> <string>客户咨询平台</string> </dict> </dict> </array> </dict> </plist>
ok到这里就结束了,写得不对 的地方请指正,有更好的方法请分享