几年前使用Cordova 进行两个app之间的相互调用和通讯;当时也是几经折腾,今天把它整理出来,理一下思路,也方便有同样需求的朋友参考

一、require引入 plugin


require("cordova!com.lampa.startapp-master");

这个插件下载 https://github.com/dengxiaoning/com.lampa.startapp

(申明:该插件参考https://github.com/lampaa/com.lampa.startapp自己实现了ios的参数传递以及 downloadApps应用下载的功能)

二、源文件分析

首选来看看这个插件的实现

plugin.xml

  <js-module src="www/startApp.js" name="startapp">
<merges target="startApp" />
</js-module>

指定了js module 的路径和调用时的名称target="startApp"

    <!-- 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>

指定插件源文件路径,根据不同平台,定义插件包名、将文件写入平台指定的路径下

startApp.js

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 导出的成功、错误回调和携带返回数据。

startApp.java(中增加方法)


/**
* 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的方法

startApp.h(中增加方法)


- (void)getExtras:(CDVInvokedUrlCommand*)command;
- (void)downloadApps:(CDVInvokedUrlCommand*)command;
- (void)exitApplication:(CDVInvokedUrlCommand*)command;

增加ISO平台下 获取应用调用时传入的参数,在未安装时根据url下载应用

startApp.m(中增加方法)


- (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);
}

三、配置应用Scheme

3.1 使用xcode 手动配置

首先将该ios文件导入xcode,点击.xcodeproj后缀的文件,xcode将会自动打开,再找到 LSApplicationQueriesScheme 为应用添加允许访问的app的白名单。 然后添加Scheme(只有这样另一个app在添加白名单时才知道写什么)。具体操作如下图

找到info 添加白名单
配置应用Scheme 配置Scheme

注意这个配置Scheme是需要调用者app和被调用app都需要设置的

同时配置ios访问设备的一些权限,否则无权限访问时应用会崩溃

找到 你的项目名-info.plist 文件打开,在最后一个array标签下加入配置


<!-- 相册 -->
<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>

操作截图

找到 项目名-info.plist 文件 添加配置

3.2 使用plugin.xml自动配置

自己写的一个配置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>

3.4 在ios 的 AppDelegate.m中增后参数接收(这个是重点)


// 在该方法中新增如下代码
- (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];
}

操作截图

四、js中调用

4.1 android平台

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);
});
}
}
});
}

4.2 iOS平台

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下载路径了)
});
}

4.3 B应用接收参数


receiveAappParams(){
startApp.getExtras(function(res){ // to do something...
console.log(res);
});
}

五、配置 plist文件

由于没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到这里就结束了,写得不对 的地方请指正,有更好的方法请分享

使用Cordova插件实现两个app之间的相互调用和通讯的更多相关文章

  1. 两个APP之间怎么调用《IT蓝豹》

    两个app之间怎么调用?   (1):通过显示Intent 启动    首先:配置好B app 的action,即AndroidManifest.xml中声明 <intent-filter> ...

  2. 通过AIDL在两个APP之间Service通信

    一.项目介绍 [知识准备] ①Android Interface definition language(aidl,android接口定义语言),其目的实现跨进程的调用.进程是程序在os中执行的载体, ...

  3. 两个App之间的跳转 并传值

    两个App之间的传值最主要的是方法是 Intent intent = getPackageManager().getLaunchIntentForPackage("com.example.a ...

  4. ios两个app之间跳转,传值的实现

    两个APP之间的跳转是通过[[UIApplication sharedApplication] openURL:url]这种方式来实现的. 1.首先设置第一个APP的url地址 2.接着设置第二个AP ...

  5. 吧,其实spring自带的BeanUtils就有这样的功能,引入spring-beans和spring-core之后,就有BeanUtils.copyProperties(a, b);可以实现两个javabean之间的相互拷贝,自己写的就当是研究咯---https://www.cnblogs.com/NieXiaoHui/p/7150928.html

    吧,其实spring自带的BeanUtils就有这样的功能,引入spring-beans和spring-core之后,就有BeanUtils.copyProperties(a, b);可以实现两个ja ...

  6. JAVA和C/C++之间的相互调用。

    在一些Android应用的开发中,需要通过JNI和 Android NDK工具实现JAVA和C/C++之间的相互调用. Java Native Interface (JNI)标准是java平台的一部分 ...

  7. C 程序与 C++ 程序之间的相互调用

    因为 C 编译器编译函数时不带参数的类型信息,只包含函数的符号名字.如 void foo( int x ) , C 编译器会将此函数编译成类似 _foo 的符号,C 链接器只要找到了调用函数的符号,就 ...

  8. C#与Javascript变量、函数之间的相互调用

    原文地址:http://blog.csdn.net/wonsoft/article/details/2595743 C#与Javascript变量.函数之间的相互调用  一.javascript调用C ...

  9. iOS中两个APP之间的跳转和通信

    app间的跳转 一:在第一个app首先要做下面这些操作: 1.在info.plist文件中的Information Property List下添加一项:URL types. 2.点开URL type ...

  10. uLua学习笔记(三):Unity3D和Lua之间的相互调用

    这篇笔记主要集中学习一下uLua和Unity3D之间相互调用的方法,我们导入了uLua之后,现在会弹出一个类似学习屏幕的东西,如下: 先赞一个! Unity3D调用Lua Unity3D调用Lua的方 ...

随机推荐

  1. Javaweb学习笔记第五弹

    preparedStatement 防止SQL注入:将敏感字符进行转义 1.获取PreparedStatement对象 String sql="selct * from 表名 where 列 ...

  2. 在CentOS中搭建NFS

    概述 NFS是一款经典的网络文件系统,在Linux上我们可以通过创建一个NFS服务在不同的服务器之间共享磁盘文件,而不用在多个服务器之间进行不断的拷贝复制,麻烦且浪费存储空间.在k8s中我们也可以使用 ...

  3. SpringCloud微服务实战——搭建企业级开发框架(五十一):微服务安全加固—自定义Gateway拦截器实现防止SQL注入/XSS攻击

      SQL注入是常见的系统安全问题之一,用户通过特定方式向系统发送SQL脚本,可直接自定义操作系统数据库,如果系统没有对SQL注入进行拦截,那么用户甚至可以直接对数据库进行增删改查等操作.   XSS ...

  4. 了解CSS Module作用域隔离原理

    CSS Module出现的背景 我们知道,Javascript发展到现在出现了众多模块化规范,比如AMD.CMD. Common JS.ESModule等,这些模块化规范能够让我们的JS实现作用域隔离 ...

  5. Spring Bean 的生命周期(详细解读)

    Spring Bean 的生命周期简单易懂.在一个 bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态.同样的,当一个 bean 不再被调用时需要进行相关的析构操作,并从 bean ...

  6. Oracle数据库 insert 插入数据 显示问号乱码的解决办法

    一.问题描述 插入的中文数据 显示成问号(乱码),其他语言如老挝文.柬文等都一样. 二.解决方案 plsql插入oracle数据乱码问题处理起来其实很简单,因为乱码问题一般都是由于编码不一致导致的,我 ...

  7. 实现一个CRDT工具库——PNCounter

    PNCounter 这段代码实现了一个PNCounter,即正负计数器.PNCounter是基于GCounter实现的,GCounter是一个只增不减的计数器,而PNCounter则是在GCounte ...

  8. php实现微信小程序消息通知

    大家好,又见面了,我是你们的朋友全 接入消息通知指引地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/callback_help.h ...

  9. 大语言模型快速推理: 在 Habana Gaudi2 上推理 BLOOMZ

    本文将展示如何在 Habana Gaudi2 上使用 Optimum Habana.Optimum Habana 是 Gaudi2 和 Transformers 库之间的桥梁.本文设计并实现了一个大模 ...

  10. Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证

    1.概述 在 Kubernetes 官方手册中给出了 "用户" 的概念,Kubernetes 集群中存在的用户包括 "普通用户" 与 "Service ...