使用Cordova插件實現兩個app之間的相互調用和通信

幾年前使用Cordova 進行兩個app之間的相互調用和通信;當時也是幾經折騰,今天把它整理出來,理一下思路,也方便有一樣需求的朋友參考java

1、require引入 plugin

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

這個插件下載 https://github.com/dengxiaoning/com.lampa.startapp
(申明:該插件參考https://github.com/lampaa/com.lampa.startapp本身實現了ios的參數傳遞以及 downloadApps應用下載的功能)android

2、源文件分析

首選來看看這個插件的實現ios

plugin.xml

<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

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 導出的成功、錯誤回調和攜帶返回數據。web

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

shell

startApp.h(中增長方法)

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

增長ISO平臺下 獲取應用調用時傳入的參數,在未安裝時根據url下載應用

apache

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

3、配置應用Scheme

3.1 使用xcode 手動配置

首先將該ios文件導入xcode,點擊.xcodeproj後綴的文件,xcode將會自動打開,再找到 LSApplicationQueriesScheme 爲應用添加容許訪問的app的白名單。 而後添加Scheme(只有這樣另外一個app在添加白名單時才知道寫什麼)。具體操做以下圖json

找到info
添加白名單
配置應用Scheme
配置Scheme
注意這個配置Scheme是須要調用者app和被調用app都須要設置的

同時配置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>

操做截圖

找到 項目名-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]; 
}

操做截圖
在這裏插入圖片描述

4、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.18080/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);
	});
}

5、配置 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到這裏就結束了,寫得不對 的地方請指正,有更好的方法請分享

相關文章
相關標籤/搜索