diff --git a/example/index.html b/example/index.html
index 266c234..115c2c5 100755
--- a/example/index.html
+++ b/example/index.html
@@ -216,6 +216,19 @@
}, (error) => {
alert("Send message fail: " + error.description);
});
+ //这里的路径以android为例
+ // var videoFilePath = "sdcard/DCIM/1.mp4";
+ // var videoFileName = "xxxxxx";
+ // var videoImagePath = "sdcard/DCIM/1.png";
+ // var videoImageFormat = "png";
+ // var videoDuration = 10;
+ // window.JMessage.sendVideoMessage({'type': 'single','username': username,'appKey': appKey,
+ // "videoFilePath":videoFilePath,"videoFileName":videoFileName,"videoImagePath":videoImagePath,"videoImageFormat":videoImageFormat,"videoDuration":videoDuration},
+ // (msg) => {
+ // console.log("sendVideo success");
+ // },(error) => {
+ // console.log("sendVideo error:"+error.description);
+ // });
}
function addConversation() {
diff --git a/package.json b/package.json
index b8c55c2..527183a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jmessage-phonegap-plugin",
- "version": "4.1.1",
+ "version": "4.1.2",
"description": "JMessage Cordova Plugin.",
"cordova": {
"id": "jmessage-phonegap-plugin",
diff --git a/src/android/JMessagePlugin.java b/src/android/JMessagePlugin.java
index 6c3a0be..ebc357c 100644
--- a/src/android/JMessagePlugin.java
+++ b/src/android/JMessagePlugin.java
@@ -4,8 +4,10 @@
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.net.Uri;
+import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
@@ -21,6 +23,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -46,6 +49,7 @@
import cn.jpush.im.android.api.content.ImageContent;
import cn.jpush.im.android.api.content.LocationContent;
import cn.jpush.im.android.api.content.TextContent;
+import cn.jpush.im.android.api.content.VideoContent;
import cn.jpush.im.android.api.content.VoiceContent;
import cn.jpush.im.android.api.enums.ContentType;
import cn.jpush.im.android.api.event.ChatRoomMessageEvent;
@@ -628,6 +632,57 @@ void sendVoiceMessage(JSONArray data, CallbackContext callback) {
}
}
+ void sendVideoMessage(JSONArray data, CallbackContext callback) {
+ boolean hasPermission = PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ if (!hasPermission) {
+ handleResult(ERR_CODE_PERMISSION, ERR_MSG_PERMISSION_WRITE_EXTERNAL_STORAGE, callback);
+ return;
+ }
+ String videoFilePath;
+ String videoFileName;
+ String videoImagePath;
+ String videoImageFormat;
+ int videoDuration;
+ Map extras = null;
+ MessageSendingOptions messageSendingOptions = null;
+ Conversation conversation;
+ try {
+ JSONObject params = data.getJSONObject(0);
+ conversation = JMessageUtils.createConversation(params);
+ if (conversation == null) {
+ handleResult(ERR_CODE_CONVERSATION, ERR_MSG_CONVERSATION, callback);
+ return;
+ }
+ videoFilePath = params.getString("videoFilePath");
+ videoFileName = params.getString("videoFileName");
+ videoImagePath = params.getString("videoImagePath");
+ videoImageFormat = params.getString("videoImageFormat");
+ videoDuration = params.getInt("videoDuration");
+ if (params.has("extras")) {
+ extras = fromJson(params.getJSONObject("extras"));
+ }
+ if (params.has("messageSendingOptions")) {
+ messageSendingOptions = toMessageSendingOptions(params.getJSONObject("messageSendingOptions"));
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
+ return;
+ }
+ try {
+ Bitmap thumbImage = BitmapFactory.decodeFile(videoImagePath);
+ File videoFile = new File(videoFilePath);
+ VideoContent videoContent = new VideoContent(thumbImage, videoImageFormat, videoFile, videoFileName, videoDuration);
+ if (extras != null) {
+ videoContent.setExtras(extras);
+ }
+ sendMessage(conversation, videoContent, messageSendingOptions, callback);
+ } catch (IOException e) {
+ e.printStackTrace();
+ handleResult(ERR_CODE_FILE, ERR_MSG_FILE, callback);
+ }
+ }
+
void sendCustomMessage(JSONArray data, CallbackContext callback) {
try {
JSONObject params = data.getJSONObject(0);
@@ -1061,6 +1116,48 @@ public void onComplete(int status, String desc, File file) {
});
}
+ void downloadVideoFile(JSONArray data, final CallbackContext callback) {
+ final Message msg;
+
+ try {
+ JSONObject params = data.getJSONObject(0);
+ msg = JMessageUtils.getMessage(params);
+ if (msg == null) {
+ handleResult(ERR_CODE_MESSAGE, ERR_MSG_MESSAGE, callback);
+ return;
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
+ return;
+ }
+
+ if (msg.getContentType() != ContentType.file) {
+ handleResult(ERR_CODE_MESSAGE, "Message type isn't video", callback);
+ return;
+ }
+
+ VideoContent content = (VideoContent) msg.getContent();
+ content.downloadVideoFile(msg, new DownloadCompletionCallback() {
+ @Override
+ public void onComplete(int status, String desc, File file) {
+ if (status == 0) {
+ JSONObject result = new JSONObject();
+ try {
+ result.put("messageId", msg.getId());
+ result.put("filePath", file.getAbsolutePath());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ handleResult(result, status, desc, callback);
+
+ } else {
+ handleResult(status, desc, callback);
+ }
+ }
+ });
+ }
+
void downloadFile(JSONArray data, final CallbackContext callback) {
final Message msg;
@@ -2630,46 +2727,67 @@ public void onEvent(OfflineMessageEvent event) throws JSONException {
final int fI = i;
switch (msg.getContentType()) {
- case image:
- ((ImageContent) msg.getContent()).downloadThumbnailImage(msg, new DownloadCompletionCallback() {
- @Override
- public void onComplete(int status, String desc, File file) {
- if (fI == fLatestMediaMessageIndex) {
- for (Message msg : offlineMsgList) {
- msgJsonArr.put(toJson(msg));
- }
- try {
- json.put("messageArray", msgJsonArr);
- } catch (JSONException e) {
- e.printStackTrace();
- }
+ case image:
+ ((ImageContent) msg.getContent()).downloadThumbnailImage(msg, new DownloadCompletionCallback() {
+ @Override
+ public void onComplete(int status, String desc, File file) {
+ if (fI == fLatestMediaMessageIndex) {
+ for (Message msg : offlineMsgList) {
+ msgJsonArr.put(toJson(msg));
+ }
+ try {
+ json.put("messageArray", msgJsonArr);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
- JSONObject eventJson = toJson("syncOfflineMessage", json);
- eventSuccess(eventJson);
- }
- }
- });
- break;
- case voice:
- ((VoiceContent) msg.getContent()).downloadVoiceFile(msg, new DownloadCompletionCallback() {
- @Override
- public void onComplete(int status, String desc, File file) {
- if (fI == fLatestMediaMessageIndex) {
- for (Message msg : offlineMsgList) {
- msgJsonArr.put(toJson(msg));
+ JSONObject eventJson = toJson("syncOfflineMessage", json);
+ eventSuccess(eventJson);
}
- try {
- json.put("messageArray", msgJsonArr);
- } catch (JSONException e) {
- e.printStackTrace();
+ }
+ });
+ break;
+ case voice:
+ ((VoiceContent) msg.getContent()).downloadVoiceFile(msg, new DownloadCompletionCallback() {
+ @Override
+ public void onComplete(int status, String desc, File file) {
+ if (fI == fLatestMediaMessageIndex) {
+ for (Message msg : offlineMsgList) {
+ msgJsonArr.put(toJson(msg));
+ }
+ try {
+ json.put("messageArray", msgJsonArr);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ JSONObject eventJson = toJson("syncOfflineMessage", json);
+ eventSuccess(eventJson);
}
+ }
+ });
+ break;
+ case video:
+ ((VideoContent) msg.getContent()).downloadVideoFile(msg, new DownloadCompletionCallback() {
+ @Override
+ public void onComplete(int status, String desc, File file) {
+ if (fI == fLatestMediaMessageIndex) {
+ for (Message msg : offlineMsgList) {
+ msgJsonArr.put(toJson(msg));
+ }
+ try {
+ json.put("messageArray", msgJsonArr);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
- JSONObject eventJson = toJson("syncOfflineMessage", json);
- eventSuccess(eventJson);
+ JSONObject eventJson = toJson("syncOfflineMessage", json);
+ eventSuccess(eventJson);
+ }
}
- }
- });
- default:
+ });
+ break;
+ default:
}
}
}
diff --git a/src/android/JMessageUtils.java b/src/android/JMessageUtils.java
index a38a906..21e1858 100644
--- a/src/android/JMessageUtils.java
+++ b/src/android/JMessageUtils.java
@@ -2,6 +2,7 @@
import android.graphics.Bitmap;
import android.os.Environment;
+import android.util.Log;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
@@ -39,6 +40,7 @@ static void handleResult(int status, String desc, CallbackContext callback) {
callback.success();
} else {
try {
+ JSONObject errorObject = getErrorObject(status, desc);
callback.error(getErrorObject(status, desc));
} catch (JSONException e) {
e.printStackTrace();
diff --git a/src/ios/Plugins/JMessageHelper.m b/src/ios/Plugins/JMessageHelper.m
index 1c73b25..c01f712 100644
--- a/src/ios/Plugins/JMessageHelper.m
+++ b/src/ios/Plugins/JMessageHelper.m
@@ -117,7 +117,7 @@ - (void)onReceiveUserLoginStatusChangeEvent:(JMSGUserLoginStatusChangeEvent *)ev
switch (event.eventType) {
case kJMSGEventNotificationLoginKicked:
[[NSNotificationCenter defaultCenter] postNotificationName:kJJMessageLoginStateChanged
- object:@{@"type":@"user_kicked"}];
+ object:@{@"type":@"user_logout"}];
break;
case kJMSGEventNotificationServerAlterPassword:
[[NSNotificationCenter defaultCenter] postNotificationName:kJJMessageLoginStateChanged
@@ -125,7 +125,11 @@ - (void)onReceiveUserLoginStatusChangeEvent:(JMSGUserLoginStatusChangeEvent *)ev
break;
case kJMSGEventNotificationUserLoginStatusUnexpected:
[[NSNotificationCenter defaultCenter] postNotificationName:kJJMessageLoginStateChanged
- object:@{@"type":@"user_login_state_unexpected"}];
+ object:@{@"type":@"user_login_status_unexpected"}];
+ break;
+ case kJMSGEventNotificationCurrentUserDeleted:
+ [[NSNotificationCenter defaultCenter] postNotificationName:kJJMessageLoginStateChanged
+ object:@{@"type":@"user_deleted"}];
break;
}
}
@@ -502,6 +506,16 @@ - (NSMutableDictionary *)messageToDictionary {
dict[@"duration"] = [voiceContent duration];
break;
}
+ case kJMSGContentTypeVideo: {
+ dict[@"type"] = @"video";
+ dict[@"mediaFilePath"] = [self getOriginMediaFilePath];
+ JMSGVideoContent *videoContent = (JMSGVideoContent *) self.content;
+ //dict[@"mediaFilePath"] = [videoContent mediaFilePath];
+ dict[@"mediaFileName"] = [videoContent fileName];
+ dict[@"videoDuration"] = [videoContent videoThumbImageLocalPath];
+ dict[@"videoDuration"] = [videoContent duration];
+ break;
+ }
case kJMSGContentTypeCustom: {
dict[@"type"] = @"custom";
JMSGCustomContent *customContent = (JMSGCustomContent *) self.content;
diff --git a/src/ios/Plugins/JMessagePlugin.h b/src/ios/Plugins/JMessagePlugin.h
index 2af77c0..3637c60 100644
--- a/src/ios/Plugins/JMessagePlugin.h
+++ b/src/ios/Plugins/JMessagePlugin.h
@@ -55,6 +55,7 @@
- (void)downloadThumbImage:(CDVInvokedUrlCommand *)command;
- (void)downloadOriginalImage:(CDVInvokedUrlCommand *)command;
- (void)downloadVoiceFile:(CDVInvokedUrlCommand *)command;
+- (void)downloadVideoFile:(CDVInvokedUrlCommand *)command;
- (void)downloadFile:(CDVInvokedUrlCommand *)command;
- (void)createConversation:(CDVInvokedUrlCommand *)command;
- (void)deleteConversation:(CDVInvokedUrlCommand *)command;
diff --git a/src/ios/Plugins/JMessagePlugin.m b/src/ios/Plugins/JMessagePlugin.m
index a368b42..83ca83f 100644
--- a/src/ios/Plugins/JMessagePlugin.m
+++ b/src/ios/Plugins/JMessagePlugin.m
@@ -295,6 +295,28 @@ - (JMSGMessage *)createMessageWithDictionary:(NSDictionary *)param type:(JMSGCon
content = [[JMSGVoiceContent alloc] initWithVoiceData:[NSData dataWithContentsOfFile: mediaPath] voiceDuration:@(duration)];
break;
}
+ case kJMSGContentTypeVideo:{
+ NSString *videoFilePath = nil;
+ NSString *videoFileName = nil;
+ NSString *videoImagePath = nil;
+ NSNumber *number = nil;
+ if(param[@"videoFilePath"]){
+ videoFilePath = param[@"videoFilePath"];
+ }
+ if(param[@"videoFileName"]){
+ videoFileName = param[@"videoFileName"];
+ }
+ if(param[@"videoImagePath"]){
+ videoImagePath = param[@"videoImagePath"];
+ }
+ if(param[@"videoDuration"]){
+ number = param[@"videoDuration"];
+ }
+ double duration = [number integerValue];
+ content = [[JMSGVideoContent alloc] initWithVideoData:[NSData dataWithContentsOfFile:videoFilePath] thumbData:[NSData dataWithContentsOfFile:videoImagePath] duration:@(duration)];
+ [(JMSGVideoContent *)content setFileName:videoFileName];
+ break;
+ }
case kJMSGContentTypeLocation:{
content = [[JMSGLocationContent alloc] initWithLatitude:param[@"latitude"] longitude:param[@"longitude"] scale:param[@"scale"] address: param[@"address"]];
break;
@@ -369,6 +391,10 @@ - (JMSGContentType)convertStringToContentType:(NSString *)str {
if ([str isEqualToString:@"voice"]) {
return kJMSGContentTypeVoice;
}
+
+ if ([str isEqualToString:@"video"]) {
+ return kJMSGContentTypeVideo;
+ }
if ([str isEqualToString:@"location"]) {
return kJMSGContentTypeLocation;
@@ -939,6 +965,35 @@ - (void)sendVoiceMessage:(CDVInvokedUrlCommand *)command {
}];
}
+- (void)sendVideoMessage:(CDVInvokedUrlCommand *)command {
+ NSDictionary * param = [command argumentAtIndex:0];
+
+ JMSGOptionalContent *messageSendingOptions = nil;
+ if (param[@"messageSendingOptions"] && [param[@"messageSendingOptions"] isKindOfClass: [NSDictionary class]]) {
+ messageSendingOptions = [self convertDicToJMSGOptionalContent:param[@"messageSendingOptions"]];
+ }
+
+ JMSGMessage *message = [self createMessageWithDictionary:param type:kJMSGContentTypeVideo];
+ if (!message) {
+ [self returnErrorWithLog:@"cannot create message, check your params and make sure the media resource is valid" command:command];
+ return;
+ }
+
+ [self getConversationWithDictionary:param callback:^(JMSGConversation *conversation, NSError *error) {
+ if (error) {
+ [self handleResultWithDictionary: nil command:command error: error];
+ return;
+ }
+
+ self.SendMsgCallbackDic[message.msgId] = command.callbackId;
+ if (messageSendingOptions) {
+ [conversation sendMessage:message optionalContent:messageSendingOptions];
+ } else {
+ [conversation sendMessage:message];
+ }
+ }];
+}
+
- (void)sendCustomMessage:(CDVInvokedUrlCommand *)command {
NSDictionary * param = [command argumentAtIndex:0];
@@ -1839,7 +1894,7 @@ - (void)downloadThumbImage:(CDVInvokedUrlCommand *)command {
}
if (message.contentType != kJMSGContentTypeImage) {
- [self returnErrorWithLog:@"It is not voice message" command:command];
+ [self returnErrorWithLog:@"It is not image message" command:command];
return;
} else {
JMSGImageContent *content = (JMSGImageContent *) message.content;
@@ -1874,7 +1929,7 @@ - (void)downloadOriginalImage:(CDVInvokedUrlCommand *)command {
}
if (message.contentType != kJMSGContentTypeImage) {
- [self returnErrorWithLog:@"It is not voice message" command:command];
+ [self returnErrorWithLog:@"It is not image message" command:command];
return;
} else {
JMSGImageContent *content = (JMSGImageContent *) message.content;
@@ -1912,7 +1967,7 @@ - (void)downloadVoiceFile:(CDVInvokedUrlCommand *)command {
}
if (message.contentType != kJMSGContentTypeVoice) {
- [self returnErrorWithLog:@"It is not image message" command:command];
+ [self returnErrorWithLog:@"It is not voice message" command:command];
return;
} else {
JMSGVoiceContent *content = (JMSGVoiceContent *) message.content;
@@ -1931,6 +1986,36 @@ - (void)downloadVoiceFile:(CDVInvokedUrlCommand *)command {
}];
}
+- (void)downloadVideoFile:(CDVInvokedUrlCommand *)command {
+ NSDictionary * param = [command argumentAtIndex:0];
+
+ [self getConversationWithDictionary:param callback:^(JMSGConversation *conversation, NSError *error) {
+ JMSGMessage *message = [conversation messageWithMessageId:param[@"messageId"]];
+
+ if (message == nil) {
+ [self returnErrorWithLog:@"cann't find this message" command: command];
+ return;
+ }
+
+ if (message.contentType != kJMSGContentTypeVideo) {
+ [self returnErrorWithLog:@"It is not video message" command:command];
+ return;
+ } else {
+ JMSGVideoContent *content = (JMSGVideoContent *) message.content;
+ [content videoDataWithProgress:nil completionHandler:^(NSData *data, NSString *objectId, NSError *error) {
+ if (error) {
+ [self handleResultWithDictionary: nil command: command error: error];
+ return;
+ }
+ JMSGFileContent *fileContent = (JMSGFileContent *) message.content;
+ [self handleResultWithDictionary:@{@"messageId": message.msgId,
+ @"filePath":[fileContent originMediaLocalPath] ? : @""}
+ command:command error:error];
+ }];
+ }
+ }];
+}
+
- (void)downloadFile:(CDVInvokedUrlCommand *)command {
NSDictionary * param = [command argumentAtIndex:0];
diff --git a/www/JMessagePlugin.js b/www/JMessagePlugin.js
index df126c2..8db3854 100644
--- a/www/JMessagePlugin.js
+++ b/www/JMessagePlugin.js
@@ -283,6 +283,27 @@ var JMessagePlugin = {
sendVoiceMessage: function(params, success, error) {
exec(success, error, PLUGIN_NAME, "sendVoiceMessage", [params]);
},
+ /**
+ * @param {object} params = {
+ * 'type': String, // 'single' / 'group'
+ * 'groupId': String, // 当 type 为 'group' 时,groupId 不能为空
+ * 'username': String, // 当 type 为 'single' 时,username 不能为空
+ * 'appKey': String, // 当 type 为 'single' 时,用于指定对象所属应用的 appKey。如果为空,默认为当前应用。
+ * 'roomId': String, // 当 type 为 'chatRoom' 时,roomId 不能为空
+ * 'videoFilePath': String, // 本地视频文件路径
+ * 'videoFileName': String, // 本地视频文件名
+ * 'videoImagePath': String, // 本地视频缩略图路径
+ * 'videoImageFormat': String, // 本地视频缩略图格式(ios可不传)
+ * 'videoDuration': int, // 本地视频播放时长,单位秒
+ * 'extras': object, // Optional. 自定义键值对 = {'key1': 'value1'}
+ * 'messageSendingOptions': MessageSendingOptions // Optional. MessageSendingOptions 对象。
+ * }
+ * @param {function} success = function (msg) {} // 以参数形式返回消息对象。
+ * @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
+ */
+ sendVideoMessage: function(params,success,error){
+ exec(success, error, PLUGIN_NAME, "sendVideoMessage", [params]);
+ },
/**
* @param {object} params = {
* 'type': String, // 'single' / 'group' / 'chatRoom'
@@ -705,6 +726,38 @@ var JMessagePlugin = {
downloadVoiceFile: function(params, success, error) {
exec(success, error, PLUGIN_NAME, "downloadVoiceFile", [params]);
},
+ /**
+ * 下载视频消息文件,如果已经下载,会直接返回本地文件路径,不会重复下载。
+ *
+ * @param {object} params = {
+ * 'type': String, // 'single' / 'group'
+ * 'groupId': String, // 目标群组 id。
+ * 'username': String, // 目标用户名。
+ * 'appKey': String, // 目标用户所属 AppKey。
+ * 'messageId': string // 指定消息 id。
+ * }
+ * @param {function} success = function ({'messageId': String, 'filePath': string}) {}
+ * @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
+ */
+ downloadVideoFile: function(params, success, error) {
+ exec(success, error, PLUGIN_NAME, "downloadVideoFile", [params]);
+ },
+ /**
+ * 下载视频消息文件,如果已经下载,会直接返回本地文件路径,不会重复下载。
+ *
+ * @param {object} params = {
+ * 'type': String, // 'single' / 'group'
+ * 'groupId': String, // 目标群组 id。
+ * 'username': String, // 目标用户名。
+ * 'appKey': String, // 目标用户所属 AppKey。
+ * 'messageId': string // 指定消息 id。
+ * }
+ * @param {function} success = function ({'messageId': String, 'filePath': string}) {}
+ * @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
+ */
+ downloadVideoFile: function(params, success, error) {
+ exec(success, error, PLUGIN_NAME, "downloadVideoFile", [params]);
+ },
/**
* 下载文件消息文件,如果已经下载,会直接返回本地文件路径,不会重复下载。
*