Commit df78610d authored by sheteng's avatar sheteng

fix

parent a3d0a99c
......@@ -26,5 +26,25 @@
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="file:/$PROJECT_DIR$/%20https:/jitpack.io%20" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="file:/$PROJECT_DIR$/ccim/%20https:/jitpack.io%20" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="file:/$PROJECT_DIR$/app/%20https:/jitpack.io%20" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://nexus.sky-shark.com/repository/ccnet-group/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/activity_main.xml" value="0.20153985507246377" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/content_main.xml" value="0.20153985507246377" />
<entry key="..\:/project/ccwangluoIm/app/src/main/res/layout/fragment_first.xml" value="0.4530812324929972" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
......
......@@ -46,4 +46,5 @@ dependencies {
compile 'com.google.protobuf:protobuf-java:3.5.1'
implementation 'com.google.protobuf:protobuf-java:3.8.0'
implementation 'com.google.protobuf:protobuf-java-util:3.8.0'
implementation 'com.guolindev.permissionx:permissionx:1.6.1'
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.ccwangluo.im;
import android.os.Bundle;
import com.ccwangluo.ccim.util.HmacUtil;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
......@@ -36,13 +37,6 @@ public class MainActivity extends AppCompatActivity {
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
binding.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
......
......@@ -22,12 +22,5 @@
<include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
This diff is collapsed.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven {
url "https://nexus.sky-shark.com/repository/ccnet-group/"
}
google()
mavenCentral()
maven { url ' https://jitpack.io ' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
......@@ -14,9 +18,12 @@ buildscript {
allprojects {
repositories {
maven {
url "https://nexus.sky-shark.com/repository/ccnet-group/"
}
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven { url ' https://jitpack.io ' }
}
}
......
......@@ -57,15 +57,12 @@ protobuf {
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.google.protobuf:protobuf-java:3.8.0'
implementation 'com.google.protobuf:protobuf-java-util:3.8.0'
api 'com.tonystark.android:socket:latest.release'
api 'com.tonystark.android:socket-server:latest.release'
implementation 'com.google.protobuf:protobuf-java:3.13.0'
implementation 'com.google.protobuf:protobuf-java-util:3.12.0'
implementation 'com.tonystark.android:socket:latest.release'
implementation 'com.tonystark.android:socket-server:latest.release'
implementation 'com.guolindev.permissionx:permissionx:1.6.1'
}
\ No newline at end of file
......@@ -3,5 +3,7 @@
package="com.ccwangluo.ccim">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>
\ No newline at end of file
package com.ccwangluo.ccim.listener;
public interface OnConnectListener {
void onSocketConnection();
void onSocketDisconnection();
}
......@@ -10,10 +10,10 @@ import java.util.HashMap;
public class CallBackManager<T> {
private final HashMap<Integer, ResultEventCallback<T>> callbackHashMap = new HashMap<>();
private final int time_out = 60 * 1000;
private static final int time_out = 60 * 1000;
public synchronized void addCallBack(int id, ResultEventCallback<T> resultEventCallback) {
public void addCallBack(int id, ResultEventCallback<T> resultEventCallback) {
callbackHashMap.put(id, resultEventCallback);
//设置60秒超时
new Handler(Looper.getMainLooper()).postDelayed(() -> {
......@@ -25,11 +25,11 @@ public class CallBackManager<T> {
},time_out);
}
public synchronized ResultEventCallback<T> getCallBack(int id) {
public ResultEventCallback<T> getCallBack(int id) {
return callbackHashMap.get(id);
}
public synchronized void removeCallBack(int id) {
public void removeCallBack(int id) {
callbackHashMap.remove(id);
}
......
package com.ccwangluo.ccim.util;
import android.util.Base64;
import android.util.Log;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import com.google.common.base.Strings;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* Created by xiang.li on 2015/2/27.
*/
public class HmacUtil {
private final static String LOG_TAG = HmacUtil.class.getName();
public static String stringToSign(String appSecret,String data) {
try {
Mac mac = Mac.getInstance("hmacSHA256");
SecretKeySpec secret = new SecretKeySpec(
appSecret.getBytes("UTF-8"), mac.getAlgorithm());
mac.init(secret);
byte[] bytes = mac.doFinal(data.getBytes());
return bytesToHex(bytes);
} catch (NoSuchAlgorithmException e) {
Log.e(LOG_TAG, "Hash algorithm SHA-1 is not supported", e);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Encoding UTF-8 is not supported", e);
} catch (InvalidKeyException e) {
Log.e(LOG_TAG, "Invalid key", e);
}
return "";
}
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if(hex.length() < 2){
sb.append(0);
}
sb.append(hex);
}
return sb.toString();
}
}
package com.ccwangluo.ccim.util;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import java.io.File;
import java.io.IOException;
public class MediaHelper {
private MediaRecorder mMediaRecorder;
private String mPath;//文件夹
private String mFilePath;//文件
private static MediaHelper mInstance;
private MediaHelper(String path) {
mPath = path;
}
/**
* 准备播放后的回调
* 这个时候文件夹里已经有文件生成了
* 如果不去释放资源将会一直进行录音
*/
public interface MediaStateListener {
void preparedDone();
}
public MediaStateListener mMediaStateListener;
public void setMediaStateListener(MediaStateListener mediaStateListener) {
mMediaStateListener = mediaStateListener;
}
/**
* 单例模式获取 MediaHelper
* 双检锁/双重校验锁
*
* @param path
* @return
*/
public static MediaHelper getInstance(String path) {
public static MediaHelper getInstance() {
if (mInstance == null) {
synchronized (MediaHelper.class) {
if (mInstance == null) {
mInstance = new MediaHelper(path);
mInstance = new MediaHelper();
}
}
}
......@@ -52,9 +32,18 @@ public class MediaHelper {
/**
* 准备录音
*/
public void prepare() {
public void prepare(Activity activity) {
try {
File fileDir = new File(mPath);
if (mMediaRecorder != null){
cancel();
}
String path;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
path = activity.getExternalFilesDir("test").getAbsolutePath();
} else {
path = activity.getCacheDir().getAbsolutePath();
}
File fileDir = new File(path);
boolean b = !fileDir.exists();
if (b) {
fileDir.mkdirs();
......@@ -72,13 +61,10 @@ public class MediaHelper {
mMediaRecorder.setOutputFile(new File(file.getAbsolutePath()));
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置MediaRecorder的音频源为麦克风
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB); // 设置音频的格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); // 设置音频的编码为AMR_NB
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AAC_ADTS); // 设置音频的格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // 设置音频的编码为AMR_NB
mMediaRecorder.prepare();
mMediaRecorder.start();
if (mMediaStateListener != null) {
mMediaStateListener.preparedDone();
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
......@@ -89,9 +75,11 @@ public class MediaHelper {
* 释放资源
*/
public void release() {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
if (mMediaRecorder != null) {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
}
}
/**
* 取消
......@@ -107,8 +95,26 @@ public class MediaHelper {
mFilePath = null;
}
}
/**
* 播放
* @param filePath
*/
public void play(String filePath) {
MediaPlayer mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepare();
//播放
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
//获取生成的文件路径
public String getFilePath() {
return mFilePath;
}
}
}
\ No newline at end of file
syntax = "proto3";
package ccim.protocol;
message CreateChannelRequest {
string name = 1;
bool open = 2;
repeated int64 user_ids = 3;
}
message CreateChannelResponse {
int64 channel_id = 1;
}
message JoinChannelRequest {
int64 channel_id = 1;
}
message JoinChannelResponse {
}
message RemoveMemberRequest {
int64 channel_id = 1;
int64 user_id = 2;
}
message RemoveMemberResponse {}
message ExitChannelRequest {
int64 channel_id = 1;
}
message ExitChannelResponse {
}
......@@ -2,6 +2,7 @@ syntax = "proto3";
package ccim.protocol;
import "channel.proto";
import "common.proto";
import "message.proto";
import "push.proto";
......@@ -10,24 +11,29 @@ message ChatRequestMessage {
RequestMessageHeader header = 1;
oneof payload {
ConnectRequest connect_req = 2;
PullContactsRequest pull_contacts_req = 3;
SearchRequest search_req = 4;
AddContactRequest add_contact_req = 5;
ContactRequestsRequest contact_requests_req = 6;
CheckContactReqRequest check_contact_req_req = 7;
CreateContactGroupRequest create_contact_group_req = 8;
MoveContactGroupRequest move_contact_group_req = 9;
DeleteContactRequest delete_contact_req = 10;
BlockContactRequest block_contact_req = 11;
ReportIllegalUserRequest report_illegal_user_req = 12;
SendMessageRequest send_msg_req = 13;
SendGroupMessageRequest send_group_msg_req = 14;
SendChannelMessageRequest send_channel_msg_req = 15;
PushPrivateMessageAckRequest push_private_msg_ack_req = 16;
PushGroupMessageAckRequest push_group_msg_ack_req = 17;
PushChannelMessageAckRequest push_channel_msg_ack_req = 18;
PullOfflineMessageRequest pull_offline_msg_req = 19;
ConnectRequest connect_req = 2; // 连接
PullContactsRequest pull_contacts_req = 3; // 拉联系人
SearchRequest search_req = 4; // 查找用户
AddContactRequest add_contact_req = 5; // 添加联系人
ContactRequestsRequest contact_requests_req = 6; // 联系人申请列表
CheckContactReqRequest check_contact_req_req = 7; // 验证联系人申请
CreateContactGroupRequest create_contact_group_req = 8; // 创建联系人群组
MoveContactGroupRequest move_contact_group_req = 9; // 移动联系人所在群组
DeleteContactRequest delete_contact_req = 10; // 删除联系人
BlockContactRequest block_contact_req = 11; // 联系人拉入黑名单
ReportIllegalUserRequest report_illegal_user_req = 12; // 举报违规用户
PullOfflineMessageRequest pull_offline_msg_req = 13; // 拉取离线消息
CreateChannelRequest create_channel_req = 21; // 创建频道
JoinChannelRequest join_channel_req = 22; // 加入频道
RemoveMemberRequest remove_member_req = 23; // 移除成员
ExitChannelRequest exit_channel_req = 24; // 退出频道
SendMessageRequest send_msg_req = 42; // 发送消息
SendChannelMessageRequest send_channel_msg_req = 43; // 发送频道消息
PushPrivateMessageAckRequest push_private_msg_ack_req = 61; // 推送私人消息成功ack
PushChannelMessageAckRequest push_channel_msg_ack_req = 62; // 推送频道消息ack
}
};
......@@ -45,19 +51,31 @@ message ChatResponseMessage {
MoveContactGroupResponse move_contact_group_res = 9;
DeleteContactResponse delete_contact_res = 10;
BlockContactResponse block_contact_res = 11;
ReportIllegalUserResponse report_illegal_user_res = 12;
SendMessageResponse send_msg_res = 13;
SendGroupMessageResponse send_group_msg_res = 14;
SendChannelMessageResponse send_channel_msg_res = 15;
PushPrivateMessageResponse push_private_msg_res = 16;
PushGroupMessageResponse push_group_msg_res = 17;
PushChannelMessageResponse push_channel_msg_res = 18;
PullOfflineMessageResponse pull_offline_msg_res = 19;
PullOfflineMessageResponse pull_offline_msg_res = 12;
CreateChannelResponse create_channel_res = 21;
JoinChannelResponse join_channel_res = 22;
RemoveMemberResponse remove_member_res = 23;
ExitChannelResponse exit_channel_res = 24;
ReportIllegalUserResponse report_illegal_user_res = 41;
SendMessageResponse send_msg_res = 42;
SendChannelMessageResponse send_channel_msg_res = 43;
PushPrivateMessageResponse push_private_msg_res = 61;
PushChannelMessageResponse push_channel_msg_res = 62;
}
};
message ConnectRequest {
string token = 1;
string app_key = 1;
int64 user_id = 2;
string username = 3;
int64 ts = 4;
string sign = 5;
// sign使用HMAC加密算法,由接入端的服务端计算完成传给接入端的客户端
// sign = HMAC(app_secret).digestToHex(app_key&user_id&username&ts&app_secret)
// ts=CurrentTimeMillis (毫秒)
}
message ConnectResponse {
......@@ -88,15 +106,15 @@ message PullContactsResponse {
Status status = 8; // 联系人状态
string ext_data = 9; // 扩展数据
}
message Group {
int64 group_id = 1;
int64 app_id = 2;
int64 owner_user_id = 3;
int32 limited = 4;
bool muted = 5;
string name = 6;
string ext_data = 7;
}
// message Group {
// int64 group_id = 1;
// int64 app_id = 2;
// int64 owner_user_id = 3;
// int32 limited = 4;
// bool muted = 5;
// string name = 6;
// string ext_data = 7;
// }
message Channel {
int64 channel_id = 1;
int64 app_id = 2;
......@@ -108,8 +126,8 @@ message PullContactsResponse {
}
repeated ContactGroup contact_groups = 2; // 联系人群组列表
repeated Contact contacts = 3; // 联系人列表
repeated Group groups = 4; // 群组
repeated Channel channels = 5; // 频道
// repeated Group groups = 4; // 群组
repeated Channel channels = 4; // 频道
}
message SearchRequest {
......@@ -134,7 +152,7 @@ message AddContactResponse {
ALREADY_SENT = 1;
NO_AUTHORITY = 2;
ALREADY_CONTACT = 3;
ACCEPT_REQ = 4;
ACCEPT_REQ = 4; // 接受对方的好友申请(对方已经发送申请,自己不必申请直接同意)
}
AddResult result = 1;
}
......
......@@ -2,22 +2,46 @@ syntax = "proto3";
package ccim.protocol;
//enum StatusCode {
// OK = 0;
// UNKNOWN_SERVER_ERROR = 100;
// AUTH_ERROR = 101;
// AUTH_INCORRECT_INPUT_ERROR = 102;
//
// CHAT_SERVICE_ERROR = 201;
//}
enum StatusCode {
STATUS_CODE_OK = 0; // 正常
STATUS_CODE_SERVER_INTERNAL_ERROR = 10000; // 服务器内部未知错误
STATUS_CODE_TOO_FREQUENTLY_ERROR = 10001; // 调用过于频繁
STATUS_CODE_UNKNOWN_REQUEST_ERROR = 10002; // 未知请求
STATUS_CODE_INVALID_ARGUMENTS_ERROR = 10003; // 无效参数
// AUTH_ERROR = 20000;
STATUS_CODE_AUTH_INCORRECT_INPUT_ERROR = 20001; // 认证无效输入
STATUS_CODE_NO_AUTH_ERROR = 20002; // 未认证
STATUS_CODE_INVALID_APP_KEY = 20003; // 无效app_key
STATUS_CODE_SIGN_EXPIRED = 20004; // 签名过期
STATUS_CODE_INVALID_SIGN = 20005; // 无效签名
// CHAT_SERVICE_ERROR = 30000;
STATUS_CODE_CHECK_CONTACT_UPDATED_ERROR = 30001; // 好友请求已同意或拒绝
STATUS_CODE_CONTACT_GROUP_EXCEEDED_LIMIT_ERROR = 30002; // 群组成员到达上限
STATUS_CODE_NOT_CONTACT_ERROR = 30101; // 非好友不能调用该api
STATUS_CODE_USER_MUTED_ERROR = 30102; // 用户被禁言
STATUS_CODE_CONTACT_BLOCKED_ERROR = 30103; // 联系人已被拉入黑名单
STATUS_CODE_CONTACT_BLOCKED_ME_ERROR = 30104; // 联系人已把我拉入黑名单
// STATUS_CODE_GROUP_NOT_MEMBER_ERROR = 30201;
// STATUS_CODE_GROUP_MUTED_ME_ERROR = 30202;
STATUS_CODE_CHANNEL_NOT_MEMBER_ERROR = 30302; // 非频道成员不能调用该api
STATUS_CODE_CHANNEL_MUTED_ME_ERROR = 30303; // 频道对我禁言
STATUS_CODE_CHANNEL_NOT_EXISTS = 30304; // 频道不存在
STATUS_CODE_CHANNEL_NOT_PERMITTED = 30305; // 频道不允许该用户加入
}
message RequestMessageHeader {
int32 version = 1;
int32 seq = 2;
int32 version = 1;
int32 seq = 2;
}
message ResponseMessageHeader {
int32 version = 1;
int32 seq = 2;
int32 code = 3;
int32 version = 1;
int32 seq = 2;
StatusCode code = 3;
}
\ No newline at end of file
......@@ -5,45 +5,45 @@ package ccim.protocol;
import "message_spec.proto";
message SendMessageRequest {
int64 receiver_user_id = 1;
string content = 2;
MessageType msg_type = 3;
int64 receiver_user_id = 1;
string content = 2;
MessageType msg_type = 3;
}
message SendMessageResponse {
int64 msg_id = 1;
int64 msg_id = 1;
}
message SendGroupMessageRequest {
int64 group_id = 1;
string content = 2;
MessageType msg_type = 3;
}
message SendGroupMessageResponse {
int64 msg_id = 1;
}
//message SendGroupMessageRequest {
// int64 group_id = 1;
// string content = 2;
// MessageType msg_type = 3;
//}
//
//message SendGroupMessageResponse {
// int64 msg_id = 1;
//}
message SendChannelMessageRequest {
int64 channel_id = 1;
string content = 2;
MessageType msg_type = 3;
int64 channel_id = 1;
string content = 2;
MessageType msg_type = 3;
}
message SendChannelMessageResponse {
int64 msg_id = 1;
int64 msg_id = 1;
}
message PullOfflineMessageRequest {
int64 last_pulled_msg_id = 1;
int64 last_pulled_msg_id = 1;
}
message PullOfflineMessageResponse {
message OfflineMessage {
int64 msg_src_id = 1;
MessageSourceType msg_src_type = 2;
ChatMessage message = 3;
int64 send_date = 4;
}
repeated OfflineMessage offline_msgs = 1;
}
\ No newline at end of file
message OfflineMessage {
int64 msg_src_id = 1;
MessageSourceType msg_src_type = 2;
ChatMessage message = 3;
int64 send_date = 4;
}
repeated OfflineMessage offline_msgs = 1;
}
......@@ -3,19 +3,22 @@ syntax = "proto3";
package ccim.protocol;
enum MessageType {
TEXT = 0;
VOICE = 1;
MESSAGE_TYPE_TEXT = 0;
MESSAGE_TYPE_VOICE = 1;
}
enum MessageSourceType {
PRIVATE = 0;
GROUP = 1;
CHANNEL = 2;
MESSAGE_SOURCE_TYPE_PRIVATE = 0;
MESSAGE_SOURCE_TYPE_CHANNEL = 1;
}
message ChatMessage {
int64 msg_id = 1;
int64 sender_user_id = 2;
MessageType msg_type = 3;
string content = 4;
int64 msg_id = 1;
int64 sender_user_id = 2;
int64 msg_src_id = 3;
MessageSourceType msg_src_type = 4;
MessageType msg_type = 5;
string content = 6;
int64 created_date = 7;
int64 modified_date = 8;
}
\ No newline at end of file
......@@ -13,16 +13,6 @@ message PushPrivateMessageAckRequest {
int64 contact_user_id = 2;
}
message PushGroupMessageResponse {
int64 group_id = 1;
ChatMessage message = 2;
}
message PushGroupMessageAckRequest {
int64 msg_id = 1;
int64 group_id = 2;
}
message PushChannelMessageResponse {
int64 channel_id = 1;
ChatMessage message = 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment