diff --git a/build.gradle b/build.gradle index 8e64390d..cfa73f87 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,10 @@ buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.3.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -20,6 +21,7 @@ allprojects { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://jitpack.io" } + google() } } diff --git a/chatapp/ChangeLog.md b/chatapp/ChangeLog.md new file mode 100644 index 00000000..ac092de5 --- /dev/null +++ b/chatapp/ChangeLog.md @@ -0,0 +1,10 @@ +### JChat v2.3.0 + +#### ChangeLog + +##### BugFix: ++ 修复表情库无法使用问题 ++ 修复用户反馈的一些其他bug + +##### NewFeature ++ 新增聊天室功能 \ No newline at end of file diff --git a/chatapp/build.gradle b/chatapp/build.gradle index 975c19c5..78d14de1 100644 --- a/chatapp/build.gradle +++ b/chatapp/build.gradle @@ -1,17 +1,16 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.1" + compileSdkVersion 26 + buildToolsVersion '28.0.3' defaultConfig { applicationId "io.jchat.android" minSdkVersion 18 targetSdkVersion 23 versionCode 61 - versionName "2.2.0" + versionName "2.3.0" multiDexEnabled true testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, JPUSH_APPKEY : "4f7aef34fb361292c566a1cd", //JPush上注册的包名对应的appkey. @@ -20,9 +19,8 @@ android { ndk { //选择要添加的对应cpu类型的.so库。 - abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a','x86', 'x86_64', 'mips', 'mips64' + abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a', 'x86', 'x86_64', 'mips', 'mips64' } - } buildTypes { release { @@ -38,31 +36,42 @@ android { } aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false - - + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + lintOptions { + disable 'GoogleAppIndexingWarning' + } } dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) - compile 'com.android.support:multidex:1.0.1' - compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT' - compile 'com.android.support:appcompat-v7:23.4.0' - compile 'com.android.support:recyclerview-v7:23.1.0' - compile 'com.android.support:design:23.1.0' - testCompile 'junit:junit:4.12' - compile 'com.jakewharton:butterknife:7.0.1' - compile 'com.github.bumptech.glide:glide:3.6.1' - compile 'com.github.w446108264:AndroidEmoji:1.0.0' - compile 'com.github.chrisbanes.photoview:library:1.2.4' - compile 'com.facebook.fresco:fresco:0.8.1' - compile 'org.greenrobot:eventbus:3.0.0' - compile 'io.reactivex:rxandroid:1.2.1' - compile project(':reclib-qq') - compile project(':reclib-testemoticons') - compile 'com.contrarywind:Android-PickerView:3.2.4' - compile 'cn.jiguang.sdk:jmessage:2.7.0' // 此处以JMessage 2.7.0 版本为例。 - compile 'cn.jiguang.sdk:jcore:1.2.3' // 此处以JCore 1.2.3 版本为例。 + implementation 'com.android.support:multidex:1.0.1' + implementation 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT' + implementation 'com.android.support:appcompat-v7:26.1.0' + implementation 'com.android.support:recyclerview-v7:26.1.0' + implementation 'com.android.support:design:26.1.0' + testImplementation 'junit:junit:4.12' + implementation 'com.jakewharton:butterknife:7.0.1' + annotationProcessor 'com.jakewharton:butterknife:7.0.1' + implementation 'com.github.bumptech.glide:glide:3.6.1' + implementation 'com.github.chrisbanes.photoview:library:1.2.4' + implementation 'com.facebook.fresco:fresco:0.8.1' + implementation 'org.greenrobot:eventbus:3.0.0' + implementation 'io.reactivex:rxandroid:1.2.1' + implementation project(':emoji') + implementation project(':reclib-qq') + implementation project(':reclib-testemoticons') + implementation 'com.contrarywind:Android-PickerView:3.2.4' + implementation 'com.yanzhenjie:permission:1.1.2' + implementation 'cn.jiguang.sdk:jmessage:2.9.0' // 此处以J + implementation 'cn.jiguang.sdk:jcore:2.0.0' + implementation 'org.greenrobot:eventbus:3.1.1' + implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-alpha-26' + implementation 'com.github.mtotschnig:StickyListHeaders:2.7.1' } diff --git a/chatapp/src/main/AndroidManifest.xml b/chatapp/src/main/AndroidManifest.xml index 10a86d91..4f8aa7ac 100644 --- a/chatapp/src/main/AndroidManifest.xml +++ b/chatapp/src/main/AndroidManifest.xml @@ -1,12 +1,10 @@ - + - - + android:protectionLevel="signature"/> @@ -21,8 +19,7 @@ - - + @@ -33,30 +30,42 @@ + + + + + + + android:value="jiguang.chat.database.UserEntry, jiguang.chat.database.FriendEntry, jiguang.chat.database.FriendRecommendEntry, jiguang.chat.database.GroupApplyEntry , jiguang.chat.database.RefuseGroupEntry"/> - + android:value="4"/> + + + + + + - - - + @@ -73,8 +82,7 @@ + android:screenOrientation="portrait"/> + android:theme="@style/BaseThemes" + android:windowSoftInputMode="stateVisible"/> - - + - - - - - - + + + + + - + + + + + + + + + + + + + + + + android:exported="false"/> - + \ No newline at end of file diff --git a/chatapp/src/main/java/jiguang/chat/MyService.java b/chatapp/src/main/java/jiguang/chat/MyService.java new file mode 100644 index 00000000..bfe28024 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/MyService.java @@ -0,0 +1,6 @@ +package jiguang.chat; + +import cn.jpush.android.service.JCommonService; + +public class MyService extends JCommonService { +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/ApplyGroupInfoActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ApplyGroupInfoActivity.java new file mode 100644 index 00000000..e04e46a8 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/ApplyGroupInfoActivity.java @@ -0,0 +1,148 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; +import jiguang.chat.application.JGApplication; +import jiguang.chat.database.GroupApplyEntry; +import jiguang.chat.database.UserEntry; +import jiguang.chat.utils.DialogCreator; + +/** + * Created by ${chenyn} on 2017/11/22. + */ + +public class ApplyGroupInfoActivity extends BaseActivity { + + private ImageView mIv_avatar; + private TextView mTv_nickName; + private TextView mTv_sign; + private TextView mTv_additionalMsg; + private TextView mTv_userName; + private TextView mTv_gender; + private TextView mTv_birthday; + private TextView mTv_address; + private Button mBtn_refusal; + private Button mBtn_agree; + private String name; + private LinearLayout mBtn_refuseAgree; + private LinearLayout mLl_state; + private TextView mTv_state; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_apply_group_info); + + initView(); + initData(); + + } + + private void initView() { + initTitle(true, true, "返回", "详细资料", false, ""); + + mIv_avatar = (ImageView) findViewById(R.id.iv_avatar); + mTv_nickName = (TextView) findViewById(R.id.tv_nickName); + mTv_sign = (TextView) findViewById(R.id.tv_sign); + mTv_additionalMsg = (TextView) findViewById(R.id.tv_additionalMsg); + mTv_userName = (TextView) findViewById(R.id.tv_userName); + mTv_gender = (TextView) findViewById(R.id.tv_gender); + mTv_birthday = (TextView) findViewById(R.id.tv_birthday); + mTv_address = (TextView) findViewById(R.id.tv_address); + + mBtn_refuseAgree = (LinearLayout) findViewById(R.id.btn_refuseAgree); + mBtn_refusal = (Button) findViewById(R.id.btn_refusal); + mBtn_agree = (Button) findViewById(R.id.btn_agree); + + mLl_state = (LinearLayout) findViewById(R.id.ll_state); + mTv_state = (TextView) findViewById(R.id.tv_state); + } + + private void initData() { + + UserEntry user = JGApplication.getUserEntry(); + String toName = getIntent().getStringExtra("toName"); + String reason = getIntent().getStringExtra("reason"); + GroupApplyEntry entry = GroupApplyEntry.getEntry(user, toName, JMessageClient.getMyInfo().getAppKey()); + + if (entry.btnState == 0) { + mBtn_refuseAgree.setVisibility(View.VISIBLE); + mLl_state.setVisibility(View.GONE); + } else if (entry.btnState == 1) { + mBtn_refuseAgree.setVisibility(View.GONE); + mLl_state.setVisibility(View.VISIBLE); + mTv_state.setText("已同意"); + } else { + mBtn_refuseAgree.setVisibility(View.GONE); + mLl_state.setVisibility(View.VISIBLE); + mTv_state.setText("已拒绝"); + } + + mTv_additionalMsg.setText(reason); + Dialog dialog = DialogCreator.createLoadingDialog(ApplyGroupInfoActivity.this, "正在加载..."); + dialog.show(); + JMessageClient.getUserInfo(toName, new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + dialog.dismiss(); + if (i == 0) { + if (userInfo.getAvatar() != null) { + mIv_avatar.setImageBitmap(BitmapFactory.decodeFile(userInfo.getAvatarFile().getPath())); + } + + mTv_nickName.setText(userInfo.getNickname()); + mTv_sign.setText(userInfo.getSignature()); + mTv_userName.setText(userInfo.getUserName()); + UserInfo.Gender gender = userInfo.getGender(); + if (gender.equals(UserInfo.Gender.male)) { + name = "男"; + } else if (gender.equals(UserInfo.Gender.female)) { + name = "女"; + } else { + name = "保密"; + } + mTv_gender.setText(name); + + mTv_address.setText(userInfo.getRegion()); + mTv_birthday.setText(getBirthday(userInfo)); + } + } + }); + + mBtn_refusal.setOnClickListener(v -> { + entry.btnState = 2; + entry.save(); + finish(); + }); + + mBtn_agree.setOnClickListener(v -> { + entry.btnState = 1; + entry.save(); + finish(); + }); + + } + + public String getBirthday(UserInfo info) { + long birthday = info.getBirthday(); + Date date = new Date(birthday); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + return dateFormat.format(date); + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/BaseActivity.java b/chatapp/src/main/java/jiguang/chat/activity/BaseActivity.java index aaf0ed2a..dec5fa2d 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/BaseActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/BaseActivity.java @@ -69,6 +69,12 @@ public void initTitle(boolean returnBtn, boolean titleLeftDesc, String titleLeft mReturn_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm.isActive() && getCurrentFocus() != null) { + if (getCurrentFocus().getWindowToken() != null) { + imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } finish(); } }); diff --git a/chatapp/src/main/java/jiguang/chat/activity/BrowserViewPagerActivity.java b/chatapp/src/main/java/jiguang/chat/activity/BrowserViewPagerActivity.java index f62bfddd..ef4d38ae 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/BrowserViewPagerActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/BrowserViewPagerActivity.java @@ -36,13 +36,16 @@ import java.lang.ref.WeakReference; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.logging.Logger; import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.callback.DownloadCompletionCallback; import cn.jpush.im.android.api.callback.ProgressUpdateCallback; import cn.jpush.im.android.api.content.ImageContent; import cn.jpush.im.android.api.enums.ContentType; +import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.Message; import jiguang.chat.R; @@ -98,6 +101,9 @@ public class BrowserViewPagerActivity extends BaseActivity { private final static int GET_NEXT_PAGE_OF_PICTURE = 0x2002; private final static int SET_CURRENT_POSITION = 0x2003; private Dialog mDialog; + public final static String MSG_JSON = "msg_json"; + public final static String MSG_LIST_JSON = "msg_list_json"; + private List messages = new ArrayList<>(); /** @@ -128,17 +134,25 @@ public void onCreate(Bundle savedInstanceState) { backgroundThread.start(); mBackgroundHandler = new BackgroundHandler(backgroundThread.getLooper()); final Intent intent = this.getIntent(); - long groupId = intent.getLongExtra(JGApplication.GROUP_ID, 0); + ConversationType conversationType = (ConversationType) intent.getSerializableExtra(JGApplication.CONV_TYPE); + String targetId = intent.getStringExtra(JGApplication.TARGET_ID); String targetAppKey = intent.getStringExtra(JGApplication.TARGET_APP_KEY); - mMessageId = intent.getIntExtra("msgId", 0); - if (groupId != 0) { - mConv = JMessageClient.getGroupConversation(groupId); - } else { - String targetId = intent.getStringExtra(JGApplication.TARGET_ID); - if (targetId != null) { - mConv = JMessageClient.getSingleConversation(targetId, targetAppKey); + if (conversationType != null) { + switch (conversationType) { + case single: + mConv = JMessageClient.getSingleConversation(targetId, targetAppKey); + break; + case group: + mConv = JMessageClient.getGroupConversation(Long.valueOf(targetId)); + break; + case chatroom: + mConv = JMessageClient.getChatRoomConversation(Long.valueOf(targetId)); + break; + default: + break; } } + mMessageId = intent.getIntExtra("msgId", 0); mStart = intent.getIntExtra("msgCount", 0); mPosition = intent.getIntExtra(JGApplication.POSITION, 0); mFromChatActivity = intent.getBooleanExtra("fromChatActivity", true); @@ -416,7 +430,11 @@ public void onPageScrolled(final int i, float v, int i2) { @Override public void onPageSelected(final int i) { if (mFromChatActivity) { - mMsg = mConv.getMessage(mMsgIdList.get(i)); + if (mConv.getType() == ConversationType.chatroom) { + mMsg = messages.get(i); + } else { + mMsg = mConv.getMessage(mMsgIdList.get(i)); + } ImageContent ic = (ImageContent) mMsg.getContent(); //每次选择或滑动图片,如果不存在本地图片则下载,显示大图 if (ic.getLocalPath() == null && i != mPosition) { @@ -478,36 +496,66 @@ private void getImgMsg() { * 初始化会话中的所有图片路径 */ private void initImgPathList() { - mMsgIdList = this.getIntent().getIntegerArrayListExtra(JGApplication.MsgIDs); - Message msg; ImageContent ic; - for (int msgID : mMsgIdList) { - msg = mConv.getMessage(msgID); - if (msg.getContentType().equals(ContentType.image)) { - ic = (ImageContent) msg.getContent(); + if (mConv.getType() == ConversationType.chatroom) { + messages.clear(); + messages.addAll(Message.fromJsonToCollection(getIntent().getStringExtra(MSG_LIST_JSON))); + for (Message message : messages) { + ic = (ImageContent) message.getContent(); if (!TextUtils.isEmpty(ic.getLocalPath())) { mPathList.add(ic.getLocalPath()); } else { mPathList.add(ic.getLocalThumbnailPath()); } } + } else { + Message msg; + mMsgIdList = this.getIntent().getIntegerArrayListExtra(JGApplication.MsgIDs); + for (int msgID : mMsgIdList) { + msg = mConv.getMessage(msgID); + if (msg.getContentType().equals(ContentType.image)) { + ic = (ImageContent) msg.getContent(); + if (!TextUtils.isEmpty(ic.getLocalPath())) { + mPathList.add(ic.getLocalPath()); + } else { + mPathList.add(ic.getLocalThumbnailPath()); + } + } + } + } + } + + private int getChatRoomMsgItem(Message msg) { + int item = 0; + for (int i = 0; i < messages.size(); i++) { + if (messages.get(i).getServerMessageId().equals(msg.getServerMessageId())) { + item = i; + break; + } } + return item; } - private void initCurrentItem() { + protected void initCurrentItem() { if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(this, this.getString(R.string.jmui_local_picture_not_found_toast), Toast.LENGTH_SHORT).show(); } - mMsg = mConv.getMessage(mMessageId); + int currentItem = 0; + if (mConv.getType() == ConversationType.chatroom) { + mMsg = Message.fromJson(getIntent().getStringExtra(MSG_JSON)); + currentItem = getChatRoomMsgItem(mMsg); + } else { + mMsg = mConv.getMessage(mMessageId); + currentItem = mMsgIdList.indexOf(mMsg.getId()); + } photoView = new PhotoView(mFromChatActivity, this); - int currentItem = mMsgIdList.indexOf(mMsg.getId()); try { ImageContent ic = (ImageContent) mMsg.getContent(); //如果点击的是第一张图片并且图片未下载过,则显示大图 - if (ic.getLocalPath() == null && mMsgIdList.indexOf(mMsg.getId()) == 0) { + if (ic.getLocalPath() == null && currentItem == 0) { downloadImage(); } - String path = mPathList.get(mMsgIdList.indexOf(mMsg.getId())); + String path = mPathList.get(currentItem); //如果发送方上传了原图 if (ic.getBooleanExtra("originalPicture") != null && ic.getBooleanExtra("originalPicture")) { mLoadBtn.setVisibility(View.GONE); @@ -781,6 +829,7 @@ public void handleMessage(android.os.Message msg) { if (activity != null) { switch (msg.what) { case DOWNLOAD_ORIGIN_IMAGE_SUCCEED: + activity.mProgressDialog.dismiss(); //更新图片并显示 Bundle bundle = msg.getData(); activity.mPathList.set(bundle.getInt(JGApplication.POSITION), bundle.getString("path")); diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChatActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChatActivity.java index 765623ec..5f5aa771 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/ChatActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/ChatActivity.java @@ -3,6 +3,7 @@ import android.Manifest; import android.app.Activity; import android.app.Dialog; +import android.app.ProgressDialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -26,15 +27,26 @@ import com.sj.emoji.EmojiBean; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; +import org.json.JSONException; +import org.json.JSONObject; + import java.io.File; import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; +import cn.jpush.im.android.api.ChatRoomManager; import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.callback.GetUserInfoListCallback; +import cn.jpush.im.android.api.callback.RequestCallback; import cn.jpush.im.android.api.content.EventNotificationContent; import cn.jpush.im.android.api.content.FileContent; import cn.jpush.im.android.api.content.ImageContent; @@ -43,6 +55,9 @@ import cn.jpush.im.android.api.enums.ContentType; import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.enums.MessageDirect; +import cn.jpush.im.android.api.event.ChatRoomMessageEvent; +import cn.jpush.im.android.api.event.ChatRoomNotificationEvent; +import cn.jpush.im.android.api.event.CommandNotificationEvent; import cn.jpush.im.android.api.event.MessageEvent; import cn.jpush.im.android.api.event.MessageReceiptStatusChangeEvent; import cn.jpush.im.android.api.event.MessageRetractEvent; @@ -52,7 +67,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.adapter.ChattingListAdapter; @@ -68,6 +82,7 @@ import jiguang.chat.pickerimage.utils.StorageType; import jiguang.chat.pickerimage.utils.StorageUtil; import jiguang.chat.pickerimage.utils.StringUtil; +import jiguang.chat.utils.CommonUtils; import jiguang.chat.utils.IdHelper; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.SimpleCommonUtils; @@ -78,9 +93,9 @@ import jiguang.chat.utils.keyboard.data.EmoticonEntity; import jiguang.chat.utils.keyboard.interfaces.EmoticonClickListener; import jiguang.chat.utils.keyboard.utils.EmoticonsKeyboardUtils; -import jiguang.chat.utils.keyboard.widget.EmoticonsEditText; import jiguang.chat.utils.keyboard.widget.FuncLayout; import jiguang.chat.utils.photovideo.takevideo.CameraActivity; +import jiguang.chat.utils.photovideo.takevideo.utils.LogUtils; import jiguang.chat.view.ChatView; import jiguang.chat.view.SimpleAppsGridView; import jiguang.chat.view.TipItem; @@ -140,11 +155,15 @@ public class ChatActivity extends BaseActivity implements FuncLayout.OnFuncKeyBo InputMethodManager mImm; private final UIHandler mUIHandler = new UIHandler(this); private boolean mAtAll = false; + private boolean isChatRoom = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } mContext = this; setContentView(R.layout.activity_chat); @@ -157,9 +176,90 @@ protected void onCreate(Bundle savedInstanceState) { ButterKnife.bind(this); - initData(); initView(); + //来自聊天室 + ConversationType conversationType = (ConversationType) getIntent().getSerializableExtra(JGApplication.CONV_TYPE); + if (conversationType != null && conversationType == ConversationType.chatroom) { + initChatRoom(getIntent().getLongExtra("chatRoomId", 0)); + mTargetId = String.valueOf(getIntent().getLongExtra("chatRoomId", 0)); + mChatView.setChatTitle(getIntent().getStringExtra("chatRoomName")); + isChatRoom = true; + } else { + initData(); + } + } + @Override + public void onDestroy() { + EventBus.getDefault().unregister(this); + super.onDestroy(); + } + + private void initChatRoom(long chatRoomId) { + ProgressDialog dialog = new ProgressDialog(mContext); + dialog.setMessage("正在进入聊天室..."); + dialog.show(); + dialog.setOnCancelListener((d) -> { + d.dismiss(); + ChatActivity.this.finish(); + }); + ChatRoomManager.enterChatRoom(chatRoomId, new RequestCallback() { + @Override + public void gotResult(int i, String s, Conversation conversation) { + if (i == 0) { + dialog.dismiss(); + if (conversation == null) { + mConv = Conversation.createChatRoomConversation(chatRoomId); + } else { + mConv = conversation; + } + initChatRoomData(); + } else if (i == 851003) { // 已经在聊天室中先退出聊天室再进入 + ChatRoomManager.leaveChatRoom(chatRoomId, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + ChatRoomManager.enterChatRoom(chatRoomId, new RequestCallback() { + @Override + public void gotResult(int i, String s, Conversation conversation) { + dialog.dismiss(); + if (i == 0) { + if (conversation == null) { + mConv = Conversation.createChatRoomConversation(chatRoomId); + } else { + mConv = conversation; + } + initChatRoomData(); + } + } + }); + } else if (i == 852004) { + dialog.dismiss(); + mConv = Conversation.createChatRoomConversation(chatRoomId); + initChatRoomData(); + } else { + dialog.dismiss(); + Toast.makeText(ChatActivity.this, "进入聊天室失败" + s, Toast.LENGTH_SHORT).show(); + finish(); + } + } + }); + } else { + dialog.dismiss(); + Toast.makeText(ChatActivity.this, "进入聊天室失败" + s, Toast.LENGTH_SHORT).show(); + finish(); + } + } + }); + } + + private void initChatRoomData() { + mChatAdapter = new ChattingListAdapter(mContext, mConv, longClickListener); + mChatView.setChatListAdapter(mChatAdapter); + mChatView.setToBottom(); + mChatView.setConversation(mConv); + mChatView.setGroupIcon(); + initEmoticonsKeyBoardBar(); } private void initData() { @@ -169,6 +269,7 @@ private void initData() { mTargetAppKey = intent.getStringExtra(TARGET_APP_KEY); mTitle = intent.getStringExtra(JGApplication.CONV_TITLE); mMyInfo = JMessageClient.getMyInfo(); + initEmoticonsKeyBoardBar(); if (!TextUtils.isEmpty(mTargetId)) { //单聊 mIsSingle = true; @@ -182,6 +283,7 @@ private void initData() { //群聊 mIsSingle = false; mGroupId = intent.getLongExtra(GROUP_ID, 0); + mTargetId = String.valueOf(mGroupId); final boolean fromGroup = intent.getBooleanExtra("fromGroup", false); if (fromGroup) { mChatView.setChatTitle(mTitle, intent.getIntExtra(MEMBERS_COUNT, 0)); @@ -257,7 +359,8 @@ public void onDropDown() { } private void initView() { - initEmoticonsKeyBoardBar(); + lvChat = (DropDownListView) findViewById(R.id.lv_chat); + ekBar = (XhsEmoticonsKeyBoard) findViewById(R.id.ek_bar); initListView(); ekBar.getEtChat().addTextChangedListener(new TextWatcher() { @@ -288,7 +391,6 @@ public void afterTextChanged(Editable arg0) { @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { - } @Override @@ -301,6 +403,31 @@ public void onTextChanged(CharSequence s, int start, int count, int after) { } } }); + + ekBar.getEtChat().setOnFocusChangeListener((v, hasFocus) -> { + String content; + if (hasFocus) { + content = "{\"type\": \"input\",\"content\": {\"message\": \"对方正在输入\"}}"; + } else { + content = "{\"type\": \"input\",\"content\": {\"message\": \"\"}}"; + } + if (mIsSingle) { + JMessageClient.sendSingleTransCommand(mTargetId, null, content, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + + } + }); + } + }); + + mChatView.getChatListView().setOnTouchListener((v, event) -> { + mChatView.getChatListView().setFocusable(true); + mChatView.getChatListView().setFocusableInTouchMode(true); + mChatView.getChatListView().requestFocus(); + CommonUtils.hideKeyboard(mContext); + return false; + }); } private void initEmoticonsKeyBoardBar() { @@ -309,31 +436,28 @@ private void initEmoticonsKeyBoardBar() { SimpleAppsGridView gridView = new SimpleAppsGridView(this); ekBar.addFuncView(gridView); - ekBar.getEtChat().setOnSizeChangedListener(new EmoticonsEditText.OnSizeChangedListener() { - @Override - public void onSizeChanged(int w, int h, int oldw, int oldh) { - scrollToBottom(); - } - }); + ekBar.getEtChat().setOnSizeChangedListener((w, h, oldw, oldh) -> scrollToBottom()); //发送按钮 - ekBar.getBtnSend().setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String mcgContent = ekBar.getEtChat().getText().toString(); - scrollToBottom(); - if (mcgContent.equals("")) { - return; - } - Message msg; - TextContent content = new TextContent(mcgContent); - if (mAtAll) { - msg = mConv.createSendMessageAtAllMember(content, null); - mAtAll = false; - } else if (null != mAtList) { - msg = mConv.createSendMessage(content, mAtList, null); - } else { - msg = mConv.createSendMessage(content); - } + //发送文本消息 + ekBar.getBtnSend().setOnClickListener(v -> { + String mcgContent = ekBar.getEtChat().getText().toString(); + scrollToBottom(); + if (mcgContent.equals("")) { + return; + } + Message msg; + TextContent content = new TextContent(mcgContent); + if (mAtAll) { + msg = mConv.createSendMessageAtAllMember(content, null); + mAtAll = false; + } else if (null != mAtList) { + msg = mConv.createSendMessage(content, mAtList, null); + } else { + LogUtils.d("ChatActivity", "create send message conversation = " + mConv + "==content==" + content.toString()); + msg = mConv.createSendMessage(content); + } + + if (!isChatRoom) { //设置需要已读回执 MessageSendingOptions options = new MessageSendingOptions(); options.setNeedReadReceipt(true); @@ -346,6 +470,10 @@ public void onClick(View v) { if (forDel != null) { forDel.clear(); } + } else { + JMessageClient.sendMessage(msg); + mChatAdapter.addMsgToList(msg); + ekBar.getEtChat().setText(""); } }); //切换语音输入 @@ -369,7 +497,12 @@ public void onClick(View v) { returnBtn(); break; case R.id.jmui_right_btn: - startChatDetailActivity(mTargetId, mTargetAppKey, mGroupId); + //如果是聊天室 + if (isChatRoom) { + startChatRoomActivity(getIntent().getLongExtra("chatRoomId", 0)); + } else { + startChatDetailActivity(mTargetId, mTargetAppKey, mGroupId); + } break; case R.id.jmui_at_me_btn: if (mUnreadMsgCnt < ChattingListAdapter.PAGE_MESSAGE_COUNT) { @@ -384,22 +517,50 @@ public void onClick(View v) { } } + private void startChatRoomActivity(long chatRoomId) { + Intent intent = new Intent(ChatActivity.this, ChatRoomInfoActivity.class); + intent.putExtra("chatRoomId", chatRoomId); + startActivity(intent); + } + @Override public void onBackPressed() { - super.onBackPressed(); returnBtn(); } private void returnBtn() { mConv.resetUnreadCount(); dismissSoftInput(); + if (mChatAdapter != null) { + mChatAdapter.stopMediaPlayer(); + } JMessageClient.exitConversation(); //发送保存为草稿事件到会话列表 EventBus.getDefault().post(new Event.Builder().setType(EventType.draft) .setConversation(mConv) .setDraft(ekBar.getEtChat().getText().toString()) .build()); - finish(); + JGApplication.delConversation = null; + if (mConv.getAllMessage() == null || mConv.getAllMessage().size() == 0) { + if (mIsSingle) { + JMessageClient.deleteSingleConversation(mTargetId); + } else { + JMessageClient.deleteGroupConversation(mGroupId); + } + JGApplication.delConversation = mConv; + } + if (isChatRoom) { + ChatRoomManager.leaveChatRoom(Long.valueOf(mTargetId), new BasicCallback() { + @Override + public void gotResult(int i, String s) { + ChatActivity.this.finish(); + ChatActivity.super.onBackPressed(); + } + }); + } else { + finish(); + super.onBackPressed(); + } } private void dismissSoftInput() { @@ -520,16 +681,18 @@ protected void onPause() { @Override protected void onResume() { String targetId = getIntent().getStringExtra(TARGET_ID); - if (!mIsSingle) { + if (mIsSingle) { + if (null != targetId) { + String appKey = getIntent().getStringExtra(TARGET_APP_KEY); + JMessageClient.enterSingleConversation(targetId, appKey); + } + } else if (!isChatRoom) { long groupId = getIntent().getLongExtra(GROUP_ID, 0); if (groupId != 0) { JGApplication.isAtMe.put(groupId, false); JGApplication.isAtall.put(groupId, false); JMessageClient.enterGroupConversation(groupId); } - } else if (null != targetId) { - String appKey = getIntent().getStringExtra(TARGET_APP_KEY); - JMessageClient.enterSingleConversation(targetId, appKey); } //历史消息中删除后返回到聊天界面刷新界面 @@ -538,16 +701,90 @@ protected void onResume() { mChatAdapter.removeMessage(msg); } } - mChatAdapter.notifyDataSetChanged(); + if (mChatAdapter != null) + mChatAdapter.notifyDataSetChanged(); //发送名片返回聊天界面刷新信息 if (SharePreferenceManager.getIsOpen()) { - initData(); + if (!isChatRoom) { + initData(); + } SharePreferenceManager.setIsOpen(false); } super.onResume(); } + public void onEvent(CommandNotificationEvent event) { + if (event.getType().equals(CommandNotificationEvent.Type.single)) { + String msg = event.getMsg(); + runOnUiThread(new Runnable() { + @Override + public void run() { + try { + JSONObject object = new JSONObject(msg); + JSONObject jsonContent = object.getJSONObject("content"); + String messageString = jsonContent.getString("message"); + if (TextUtils.isEmpty(messageString)) { + mChatView.setTitle(mConv.getTitle()); + } else { + mChatView.setTitle(messageString); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + }); + } + } + + public void onEventMainThread(ChatRoomMessageEvent event) { + List messages = event.getMessages(); + mChatAdapter.addMsgListToList(messages); + } + + public void onEventMainThread(ChatRoomNotificationEvent event) { + try { + Constructor constructor = EventNotificationContent.class.getDeclaredConstructor(); + constructor.setAccessible(true); + List messages = new ArrayList<>(); + switch (event.getType()) { + case add_chatroom_admin: + case del_chatroom_admin: + event.getTargetUserInfoList(new GetUserInfoListCallback() { + @Override + public void gotResult(int i, String s, List list) { + if (i == 0) { + for (UserInfo userInfo : list) { + try { + EventNotificationContent content = (EventNotificationContent) constructor.newInstance(); + Field field = content.getClass().getSuperclass().getDeclaredField("contentType"); + field.setAccessible(true); + field.set(content, ContentType.eventNotification); + String user = userInfo.getUserID() == JMessageClient.getMyInfo().getUserID() + ? "你" : TextUtils.isEmpty(userInfo.getNickname()) ? userInfo.getUserName() : userInfo.getNickname(); + String result = event.getType() == ChatRoomNotificationEvent.Type.add_chatroom_admin ? "被设置成管理员" : "被取消管理员"; + content.setStringExtra("msg", user + result); + if (mConv != null) { + messages.add(mConv.createSendMessage(content)); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + if (messages.size() > 0) { + mChatAdapter.addMsgListToList(messages); + } + } + } + }); + break; + default: + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public void onEvent(MessageEvent event) { final Message message = event.getMessage(); @@ -565,20 +802,16 @@ public void onEvent(MessageEvent event) { //群主把当前用户添加到群聊,则显示聊天详情按钮 refreshGroupNum(); if (userNames.contains(mMyInfo.getNickname()) || userNames.contains(mMyInfo.getUserName())) { - runOnUiThread(new Runnable() { - @Override - public void run() { - mChatView.showRightBtn(); - } - }); + runOnUiThread(() -> mChatView.showRightBtn()); } break; case group_member_removed: //删除群成员事件 userNames = ((EventNotificationContent) message.getContent()).getUserNames(); + UserInfo operator = ((EventNotificationContent) message.getContent()).getOperatorUserInfo(); //群主删除了当前用户,则隐藏聊天详情按钮 - if (userNames.contains(mMyInfo.getNickname()) || userNames.contains(mMyInfo.getUserName())) { + if ((userNames.contains(mMyInfo.getNickname()) || userNames.contains(mMyInfo.getUserName())) && operator.getUserID() != mMyInfo.getUserID()) { runOnUiThread(new Runnable() { @Override public void run() { @@ -696,6 +929,9 @@ private void refreshGroupNum() { @Override public void onContentLongClick(final int position, View view) { + if (isChatRoom) { + return; + } final Message msg = mChatAdapter.getMessage(position); if (msg == null) { @@ -915,6 +1151,7 @@ public void onEventMainThread(MessageReceiptStatusChangeEvent event) { } } + @Subscribe (threadMode = ThreadMode.MAIN) public void onEventMainThread(ImageEvent event) { Intent intent; switch (event.getFlag()) { @@ -946,9 +1183,9 @@ public void onEventMainThread(ImageEvent event) { Toast.makeText(this, "请在应用管理中打开“位置”访问权限!", Toast.LENGTH_LONG).show(); } else { intent = new Intent(mContext, MapPickerActivity.class); + intent.putExtra(JGApplication.CONV_TYPE, mConv.getType()); intent.putExtra(JGApplication.TARGET_ID, mTargetId); intent.putExtra(JGApplication.TARGET_APP_KEY, mTargetAppKey); - intent.putExtra(JGApplication.GROUP_ID, mGroupId); intent.putExtra("sendLocation", true); startActivityForResult(intent, JGApplication.REQUEST_CODE_SEND_LOCATION); } @@ -963,16 +1200,16 @@ public void onEventMainThread(ImageEvent event) { intent = new Intent(mContext, SendFileActivity.class); intent.putExtra(JGApplication.TARGET_ID, mTargetId); intent.putExtra(JGApplication.TARGET_APP_KEY, mTargetAppKey); - intent.putExtra(JGApplication.GROUP_ID, mGroupId); + intent.putExtra(JGApplication.CONV_TYPE, mConv.getType()); startActivityForResult(intent, JGApplication.REQUEST_CODE_SEND_FILE); } break; case JGApplication.BUSINESS_CARD: intent = new Intent(mContext, FriendListActivity.class); - intent.putExtra("isSingle", mIsSingle); - intent.putExtra("userId", mTargetId); - intent.putExtra("groupId", mGroupId); - startActivity(intent); + intent.putExtra(JGApplication.CONV_TYPE, mConv.getType()); + intent.putExtra(JGApplication.TARGET_ID, mTargetId); + intent.putExtra(JGApplication.TARGET_APP_KEY, mTargetAppKey);; + startActivityForResult(intent, JGApplication.REQUEST_CODE_FRIEND_LIST); break; case JGApplication.TACK_VIDEO: case JGApplication.TACK_VOICE: @@ -995,6 +1232,20 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { case RequestCode.PICK_IMAGE://4 onPickImageActivityResult(requestCode, data); break; + case JGApplication.REQUEST_CODE_FRIEND_LIST: + // 发送名片成功后,聊天室需要添加消息 + if (resultCode == RESULT_OK && isChatRoom) { + String msgJson = data.getStringExtra(JGApplication.MSG_JSON); + if (msgJson != null) { + Message msg = Message.fromJson(msgJson); + if (msg != null) { + mChatAdapter.addMsgToList(msg); + mChatAdapter.notifyDataSetChanged(); + } + } + } + break; + } switch (resultCode) { @@ -1030,7 +1281,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { public void gotResult(int responseCode, String responseMessage, ImageContent imageContent) { if (responseCode == 0) { Message msg = mConv.createSendMessage(imageContent); - handleSendMsg(msg.getId()); + handleSendMsg(msg); } } }); @@ -1043,7 +1294,7 @@ public void gotResult(int responseCode, String responseMessage, ImageContent ima FileContent fileContent = new FileContent(new File(path)); fileContent.setStringExtra("video", "mp4"); Message msg = mConv.createSendMessage(fileContent); - handleSendMsg(msg.getId()); + handleSendMsg(msg); } catch (Exception e) { e.printStackTrace(); } @@ -1075,9 +1326,11 @@ public void gotResult(int responseCode, String responseMessage, ImageContent ima mChatView.setToBottom(); break; case JGApplication.RESULT_CODE_SEND_FILE: - int[] intArrayExtra = data.getIntArrayExtra(MsgIDs); - for (int msgId : intArrayExtra) { - handleSendMsg(msgId); + String msgListJson = data.getStringExtra(JGApplication.MSG_LIST_JSON); + if (msgListJson != null) { + for (Message msg : Message.fromJsonToCollection(msgListJson)) { + handleSendMsg(msg); + } } break; case JGApplication.RESULT_CODE_CHAT_DETAIL: @@ -1141,7 +1394,7 @@ public void sendImage(final File file, boolean isOrig) { public void gotResult(int responseCode, String responseMessage, ImageContent imageContent) { if (responseCode == 0) { Message msg = mConv.createSendMessage(imageContent); - handleSendMsg(msg.getId()); + handleSendMsg(msg); } } }); @@ -1160,7 +1413,7 @@ public void gotResult(int responseCode, String responseMessage, ImageContent ima if (responseCode == 0) { imageContent.setStringExtra("jiguang", "xiong"); Message msg = mConv.createSendMessage(imageContent); - handleSendMsg(msg.getId()); + handleSendMsg(msg); } else { ToastUtil.shortToast(mContext, responseMessage); } @@ -1171,10 +1424,10 @@ public void gotResult(int responseCode, String responseMessage, ImageContent ima /** * 处理发送图片,刷新界面 * - * @param data intent + * @param msg */ - private void handleSendMsg(int data) { - mChatAdapter.setSendMsgs(data); + private void handleSendMsg(Message msg) { + mChatAdapter.setSendMsgs(msg); mChatView.setToBottom(); } diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChatDetailActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChatDetailActivity.java index 050e17ac..3ca35bd5 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/ChatDetailActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/ChatDetailActivity.java @@ -47,13 +47,14 @@ public class ChatDetailActivity extends BaseActivity { private static final int ADD_FRIEND_REQUEST_CODE = 3; public static final int GROUP_DESC = 70; - public static final int FLAGS_GROUP_DESC = 71; public static final String GROUP_DESC_KEY = "group_desc_key"; public static final int GROUP_NAME = 72; - public static final int FLAGS_GROUP_NAME = 73; public static final String GROUP_NAME_KEY = "group_name_key"; + private static final int GROUP_DESC_COUNT = 250; + private static final int GROUP_NAME_COUNT = 64; + private long groupID; @@ -104,13 +105,15 @@ public void updateGroupNameDesc(long groupId, int nameOrDesc) { this.groupID = groupId; Intent intent = new Intent(ChatDetailActivity.this, NickSignActivity.class); if (nameOrDesc == 1) { - intent.setFlags(FLAGS_GROUP_NAME); - intent.putExtra("group_name", mGroupName); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.GROUP_NAME); + intent.putExtra(NickSignActivity.COUNT, GROUP_NAME_COUNT); + intent.putExtra(NickSignActivity.DESC, mGroupName); } else { - intent.setFlags(FLAGS_GROUP_DESC); - intent.putExtra("group_desc", mGroupDesc); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.GROUP_DESC); + intent.putExtra(NickSignActivity.COUNT, GROUP_DESC_COUNT); + intent.putExtra(NickSignActivity.DESC, mGroupDesc); } - startActivityForResult(intent, GROUP_NAME); + startActivityForResult(intent, nameOrDesc == 1 ? GROUP_NAME : GROUP_DESC); } @Override diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChatRoomDetailActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomDetailActivity.java new file mode 100644 index 00000000..53c85bf6 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomDetailActivity.java @@ -0,0 +1,78 @@ +package jiguang.chat.activity; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.widget.Button; +import android.widget.TextView; + +import java.util.Collections; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.enums.ConversationType; +import cn.jpush.im.android.api.model.ChatRoomInfo; +import jiguang.chat.R; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.dialog.LoadDialog; + +/** + * Created by ${chenyn} on 2017/10/31. + */ + +@SuppressLint("Registered") +public class ChatRoomDetailActivity extends BaseActivity { + + private TextView mChatRoomName; + private TextView mChatRoomID; + private TextView mChatRoomMember; + private TextView mChatRoomDesc; + private Button mEnterChatRoom; + private ChatRoomInfo mInfo; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_chat_room_detail); + initView(); + initData(); + } + + private void initData() { + LoadDialog.show(ChatRoomDetailActivity.this, "正在加载..."); + long chatRoomId = getIntent().getLongExtra("chatRoomId", 0); + ChatRoomManager.getChatRoomInfos(Collections.singleton(chatRoomId), new RequestCallback>() { + @Override + public void gotResult(int i, String s, List chatRoomInfos) { + LoadDialog.dismiss(ChatRoomDetailActivity.this); + if (i == 0) { + mInfo = chatRoomInfos.get(0); + mChatRoomName.setText(mInfo.getName()); + mChatRoomID.setText(mInfo.getRoomID() + ""); + mChatRoomDesc.setText(mInfo.getDescription()); + mChatRoomMember.setText(mInfo.getTotalMemberCount() + ""); + } + } + }); + mEnterChatRoom.setOnClickListener(v -> { + Intent intent = new Intent(ChatRoomDetailActivity.this, ChatActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + intent.putExtra(JGApplication.CONV_TYPE, ConversationType.chatroom); + intent.putExtra("chatRoomId", chatRoomId); + intent.putExtra("chatRoomName", mInfo.getName()); + startActivity(intent); + }); + } + + private void initView() { + initTitle(true, true, "详细资料", "", false, ""); + mChatRoomName = (TextView) findViewById(R.id.tv_chatRoomName); + mChatRoomID = (TextView) findViewById(R.id.tv_chatRoomID); + mChatRoomMember = (TextView) findViewById(R.id.tv_chatRoomMember); + mChatRoomDesc = (TextView) findViewById(R.id.tv_chatRoomDesc); + mEnterChatRoom = (Button) findViewById(R.id.btn_enterChatRoom); + + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChatRoomInfoActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomInfoActivity.java new file mode 100644 index 00000000..50647b9d --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomInfoActivity.java @@ -0,0 +1,222 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.event.ChatRoomNotificationEvent; +import cn.jpush.im.android.api.model.ChatRoomInfo; +import cn.jpush.im.android.api.model.UserInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.adapter.ChatRoomKeeperGridAdapter; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.DialogCreator; +import jiguang.chat.utils.ToastUtil; +import jiguang.chat.view.NoScrollGridView; + +/** + * Created by ${chenyn} on 2017/11/8. + */ + +public class ChatRoomInfoActivity extends BaseActivity implements View.OnClickListener { + + private TextView mTvChatRoomName, mTvChatRoomDesc, mTvChatRoomOwner; + private NoScrollGridView mGvChatRoomKeeper; + private ChatRoomKeeperGridAdapter mGridAdapter; + private List keeperList = new ArrayList<>(); + private List keeperListDisplay = new ArrayList<>(); + private ChatRoomInfo mChatRoomInfo; + private UserInfo ownerInfo; + private long roomId; + private boolean isOwner; + private Dialog exitDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat_room_info); + initTitle(true, true, "聊天室资料", "", false, ""); + initData(); + } + + @Override + public void onClick(View v) { + Intent intent = new Intent(); + switch (v.getId()) { + case R.id.ll_chat_room_name: + intent.setClass(ChatRoomInfoActivity.this, NickSignActivity.class); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.CHAT_ROOM_NAME); + intent.putExtra(NickSignActivity.DESC, mChatRoomInfo != null ? mChatRoomInfo.getName() : ""); + startActivity(intent); + break; + case R.id.ll_chat_room_desc: + intent.setClass(ChatRoomInfoActivity.this, NickSignActivity.class); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.CHAT_ROOM_DESC); + intent.putExtra(NickSignActivity.DESC, mChatRoomInfo != null ? mChatRoomInfo.getDescription() : ""); + startActivity(intent); + break; + case R.id.ll_chat_room_keeper: + intent.setClass(ChatRoomInfoActivity.this, ChatRoomKeeperActivity.class); + intent.putExtra(JGApplication.ROOM_ID, roomId); + intent.putExtra(ChatRoomKeeperActivity.IS_OWNER, isOwner); + startActivity(intent); + break; + case R.id.ll_chat_room_owner: + if (isOwner) { + intent.setClass(ChatRoomInfoActivity.this, PersonalActivity.class); + } else { + intent.setClass(ChatRoomInfoActivity.this, GroupUserInfoActivity.class); + intent.putExtra(GroupUserInfoActivity.IS_FROM_GROUP, false); + intent.putExtra(JGApplication.NAME, ownerInfo != null ? ownerInfo.getUserName() : ""); + intent.putExtra(JGApplication.TARGET_APP_KEY, ownerInfo != null ? ownerInfo.getAppKey() : ""); + } + startActivity(intent); + break; + case R.id.btn_exit_room: + View.OnClickListener listener = (v1) -> { + switch (v1.getId()) { + case R.id.jmui_cancel_btn: + exitDialog.cancel(); + break; + case R.id.jmui_commit_btn: + exitChatRoom(); + exitDialog.cancel(); + break; + } + }; + exitDialog = DialogCreator.createBaseDialogWithTitle(ChatRoomInfoActivity.this, "确定退出聊天室", listener); + exitDialog.show(); + break; + default: + break; + } + } + + private void exitChatRoom() { + Dialog loadingDialog = DialogCreator.createLoadingDialog(ChatRoomInfoActivity.this, + "正在处理"); + loadingDialog.show(); + ChatRoomManager.leaveChatRoom(roomId, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + loadingDialog.dismiss(); + if (i == 0) { + Intent intent = new Intent(); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.setClass(ChatRoomInfoActivity.this, MainActivity.class); + startActivity(intent); + } else { + ToastUtil.shortToast(ChatRoomInfoActivity.this, "退出失败"); + } + } + }); + } + + private void initData() { + mTvChatRoomName = (TextView) findViewById(R.id.tv_chatRoomName); + mTvChatRoomDesc = (TextView) findViewById(R.id.tv_chatRoomDesc); + mTvChatRoomOwner = (TextView) findViewById(R.id.tv_chatRoomOwner); + mGvChatRoomKeeper = (NoScrollGridView) findViewById(R.id.grid_chatRommKeeper); + mGvChatRoomKeeper.setClickable(false); + mGvChatRoomKeeper.setPressed(false); + mGvChatRoomKeeper.setEnabled(false); + roomId = getIntent().getLongExtra("chatRoomId", 0); + findViewById(R.id.ll_chat_room_name).setOnClickListener(this); + findViewById(R.id.ll_chat_room_desc).setOnClickListener(this); + findViewById(R.id.ll_chat_room_keeper).setOnClickListener(this); + findViewById(R.id.ll_chat_room_owner).setOnClickListener(this); + findViewById(R.id.btn_exit_room).setOnClickListener(this); + Dialog loadingDialog = DialogCreator.createLoadingDialog(this, "正在加载..."); + loadingDialog.show(); + AtomicInteger taskCount = new AtomicInteger(2); + ChatRoomManager.getChatRoomInfos(Collections.singleton(roomId), new RequestCallback>() { + @Override + public void gotResult(int i, String s, List chatRoomInfos) { + if (i == 0) { + mChatRoomInfo = chatRoomInfos.get(0); + mTvChatRoomName.setText(mChatRoomInfo.getName()); + mTvChatRoomDesc.setText(mChatRoomInfo.getDescription()); + mChatRoomInfo.getOwnerInfo(new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + if (i == 0) { + ownerInfo = userInfo; + isOwner = (ownerInfo.getUserID() == JMessageClient.getMyInfo().getUserID()); + mTvChatRoomOwner.setText(ownerInfo.getDisplayName()); + } + if (taskCount.decrementAndGet() == 0) { + loadingDialog.dismiss(); + } + } + }); + } else { + if (taskCount.decrementAndGet() == 0) { + loadingDialog.dismiss(); + } + } + } + }); + ChatRoomManager.getChatRoomAdminList(roomId, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List userInfos) { + if (i == 0) { + keeperList.clear(); + keeperListDisplay.clear(); + keeperList.addAll(userInfos); + if (keeperList.size() > 5) { + keeperListDisplay.addAll(userInfos.subList(0, 5)); // 只取5个 + } else { + keeperListDisplay.addAll(userInfos); + } + } + mGvChatRoomKeeper.setNumColumns(keeperListDisplay.size()); + mGridAdapter = new ChatRoomKeeperGridAdapter(ChatRoomInfoActivity.this, keeperListDisplay); + mGvChatRoomKeeper.setAdapter(mGridAdapter); + if (taskCount.decrementAndGet() == 0) { + loadingDialog.dismiss(); + } + } + }); + } + + public void onEvent(ChatRoomNotificationEvent event) { + switch (event.getType()) { + case del_chatroom_admin: + case add_chatroom_admin: + ChatRoomManager.getChatRoomAdminList(roomId, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List userInfos) { + if (i == 0) { + keeperList.clear(); + keeperListDisplay.clear(); + keeperList.addAll(userInfos); + if (keeperList.size() > 5) { + keeperListDisplay.addAll(userInfos.subList(0, 5)); // 只取5个 + } else { + keeperListDisplay.addAll(userInfos); + } + } + mGvChatRoomKeeper.setNumColumns(keeperListDisplay.size()); + mGridAdapter.notifyDataSetChanged(); + } + }); + break; + default: + break; + + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChatRoomKeeperActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomKeeperActivity.java new file mode 100644 index 00000000..5fda44c2 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/ChatRoomKeeperActivity.java @@ -0,0 +1,265 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.text.Editable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TextView; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.event.ChatRoomNotificationEvent; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; +import jiguang.chat.adapter.ChatRoomKeeperListAdapter; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.DialogCreator; +import jiguang.chat.utils.HandleResponseCode; +import jiguang.chat.utils.pinyin.HanyuPinyin; + +public class ChatRoomKeeperActivity extends BaseActivity { + private TextView mTvNullKeeper; + private ListView mLvKeeper; + private EditText mEtSearch; + private List mKeepers = new ArrayList<>(); + private List mShowKeeperList = new ArrayList<>(); + private List mPinyinList = new ArrayList(); + private ChatRoomKeeperListAdapter mAdapter; + private String mSearchText; + private MyHandler myHandler; + private static final int SEARCH_KEEPER = 0; + private static final int SEARCH_MEMBER_SUCCESS = 1; + private long roomID; + public static final String IS_OWNER = "isOwner"; + private boolean isOwner; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_chat_room_keeper); + initData(); + } + + private void initData() { + initTitle(true, true, "管理员", "", true, "添加"); + roomID = getIntent().getLongExtra(JGApplication.ROOM_ID, 0); + isOwner = getIntent().getBooleanExtra(IS_OWNER, false); + if (!isOwner) { + mJmui_commit_btn.setVisibility(View.GONE); + } + mJmui_commit_btn.setOnClickListener((v) -> { + Intent intent = new Intent(ChatRoomKeeperActivity.this, SearchForChatRoomActivity.class); + intent.putExtra(JGApplication.ROOM_ID, roomID); + startActivity(intent); + }); + mTvNullKeeper = (TextView) findViewById(R.id.null_chatRoomKeeper); + mLvKeeper = (ListView) findViewById(R.id.lv_chatRoomKeeper); + mEtSearch = (EditText) findViewById(R.id.search_et); + mEtSearch.addTextChangedListener(watcher); + myHandler = new MyHandler(getMainLooper(), this); + Dialog loadingDialog = DialogCreator.createLoadingDialog(this, "正在加载..."); + loadingDialog.show(); + ChatRoomManager.getChatRoomAdminList(roomID, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List userInfos) { + if (i == 0) { + if (userInfos.size() > 0) { + mKeepers.clear(); + mKeepers.addAll(userInfos); + addAll(false); + } else { + mTvNullKeeper.setVisibility(View.VISIBLE); + } + mAdapter = new ChatRoomKeeperListAdapter(ChatRoomKeeperActivity.this, mShowKeeperList, roomID, isOwner); + mLvKeeper.setAdapter(mAdapter); + mLvKeeper.setOnItemClickListener(mAdapter); + loadingDialog.dismiss(); + } else { + loadingDialog.dismiss(); + HandleResponseCode.onHandle(ChatRoomKeeperActivity.this, i, false); + } + } + }); + + } + + TextWatcher watcher = new TextWatcher() { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mSearchText = s.toString().trim(); + myHandler.removeMessages(SEARCH_KEEPER); + myHandler.sendMessageDelayed(myHandler.obtainMessage(SEARCH_KEEPER), 200); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }; + + public class ItemModel { + public UserInfo data; + public SpannableString highlight; + public int sortIndex; + } + + public void onEventMainThread(ChatRoomNotificationEvent event) { + switch (event.getType()) { + case add_chatroom_admin: + case del_chatroom_admin: + if (mAdapter != null) { + ChatRoomManager.getChatRoomAdminList(roomID, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List userInfos) { + if (i == 0) { + mKeepers.clear(); + mKeepers.addAll(userInfos); + addAll(true); + mTvNullKeeper.setVisibility(userInfos.size() > 0 ? View.GONE : View.VISIBLE); + } + } + }); + } + break; + default: + break; + } + + } + + private class MyHandler extends Handler { + private final WeakReference mActivity; + public MyHandler(Looper looper, ChatRoomKeeperActivity mActivity) { + super(looper); + this.mActivity = new WeakReference<>(mActivity); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + switch (msg.what) { + case SEARCH_KEEPER: + if (mShowKeeperList != null) { + mShowKeeperList.clear(); + } + filterData(); + break; + case SEARCH_MEMBER_SUCCESS: + ChatRoomKeeperActivity activity = mActivity.get(); + if (activity != null && activity.mAdapter != null) { + activity.mAdapter.notifyDataSetChanged(); + } + break; + default: + break; + + } + } + } + + + /** + * 根据输入框输入的字符过滤群成员 + */ + private void filterData() { + if (TextUtils.isEmpty(mSearchText)) { + addAll(true); + } else { + String displayName, pinyin; + int sort; + SpannableString result; + ItemModel model; + UserInfo userInfo; + for (int i = 0; i < mPinyinList.size(); i++) { + sort = 0; + userInfo = mKeepers.get(i); + displayName = userInfo.getDisplayName(); + result = new SpannableString(displayName); + //先进行拼音匹配 + pinyin = mPinyinList.get(i).toLowerCase(); + int offset = pinyin.indexOf(mSearchText.toLowerCase()); + if (offset != -1) { + model = new ItemModel(); + sort += mSearchText.length(); + result.setSpan(new ForegroundColorSpan(Color.RED), offset, + offset + mSearchText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + //进行直接匹配 + int index = displayName.indexOf(mSearchText); + if (index != -1) { + sort += mSearchText.length(); + result.setSpan(new ForegroundColorSpan(Color.RED), index, + index + mSearchText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + model.data = userInfo; + model.highlight = result; + model.sortIndex = sort; + mShowKeeperList.add(model); + continue; + } + model.data = userInfo; + model.highlight = result; + model.sortIndex = sort; + mShowKeeperList.add(model); + //进行直接匹配 + } else { + int index = displayName.indexOf(mSearchText); + if (index != -1) { + sort += mSearchText.length(); + result.setSpan(new ForegroundColorSpan(Color.RED), index, + index + mSearchText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + model = new ItemModel(); + model.data = userInfo; + model.highlight = result; + model.sortIndex = sort; + mShowKeeperList.add(model); + } + } + } + } + + myHandler.sendEmptyMessage(SEARCH_MEMBER_SUCCESS); + } + + private void addAll(boolean needSendMessage) { + String nickname, pinyin; + ItemModel itemModel; + mPinyinList.clear(); + mShowKeeperList.clear(); + for (UserInfo userInfo: mKeepers) { + itemModel = new ItemModel(); + itemModel.data = userInfo; + nickname = userInfo.getNickname(); + if (TextUtils.isEmpty(nickname)) { + nickname = userInfo.getUserName(); + } + pinyin = HanyuPinyin.getInstance().getStringPinYin(nickname); + mPinyinList.add(pinyin); + itemModel.highlight = new SpannableString(nickname); + mShowKeeperList.add(itemModel); + } + if (needSendMessage) { + myHandler.sendEmptyMessage(SEARCH_MEMBER_SUCCESS); + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/ChooseAtMemberActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ChooseAtMemberActivity.java index 87d00104..2088bc6f 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/ChooseAtMemberActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/ChooseAtMemberActivity.java @@ -23,7 +23,7 @@ import jiguang.chat.utils.keyboard.widget.EmoticonsEditText; import jiguang.chat.utils.pinyin.UserComparator; import jiguang.chat.utils.sidebar.SideBar; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** diff --git a/chatapp/src/main/java/jiguang/chat/activity/CreateGroupActivity.java b/chatapp/src/main/java/jiguang/chat/activity/CreateGroupActivity.java index 9f2026c3..ede79a78 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/CreateGroupActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/CreateGroupActivity.java @@ -1,6 +1,5 @@ package jiguang.chat.activity; -import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -20,26 +19,18 @@ import java.util.List; import cn.jpush.im.android.api.JMessageClient; -import cn.jpush.im.android.api.callback.CreateGroupCallback; import cn.jpush.im.android.api.callback.GetUserInfoCallback; -import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; -import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.adapter.CreateGroupAdapter; import jiguang.chat.adapter.StickyListAdapter; import jiguang.chat.application.JGApplication; import jiguang.chat.database.FriendEntry; import jiguang.chat.database.UserEntry; -import jiguang.chat.entity.Event; -import jiguang.chat.entity.EventType; -import jiguang.chat.utils.DialogCreator; -import jiguang.chat.utils.ToastUtil; import jiguang.chat.utils.keyboard.utils.EmoticonsKeyboardUtils; import jiguang.chat.utils.pinyin.PinyinComparator; import jiguang.chat.utils.sidebar.SideBar; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** @@ -60,7 +51,6 @@ public class CreateGroupActivity extends BaseActivity implements View.OnClickLis private GridView imageSelectedGridView; private CreateGroupAdapter mGroupAdapter; private Context mContext; - private Dialog mLoadingDialog; private FriendEntry mFriendEntry; private TextView mTv_noFriend; private TextView mTv_noFilter; @@ -143,66 +133,16 @@ public void onClick(View v) { break; case R.id.finish_btn: //拿到所选择的userName - final ArrayList selectedUser = mAdapter.getSelectedUser(); - mLoadingDialog = DialogCreator.createLoadingDialog(mContext, - mContext.getString(R.string.creating_hint)); - mLoadingDialog.show(); - JMessageClient.createGroup("", "", new CreateGroupCallback() { - @Override - public void gotResult(int responseCode, String responseMsg, final long groupId) { - if (responseCode == 0) { - if (selectedUser.size() > 0) { - JMessageClient.addGroupMembers(groupId, selectedUser, new BasicCallback() { - @Override - public void gotResult(int responseCode, String responseMessage) { - mLoadingDialog.dismiss(); - if (responseCode == 0) { - //如果创建群组时添加了人,那么就在size基础上加上自己 - createGroup(groupId, selectedUser.size() + 1); - } else if (responseCode == 810007) { - ToastUtil.shortToast(mContext, "不能添加自己"); - } else { - ToastUtil.shortToast(mContext, "添加失败"); - } - } - }); - } else { - mLoadingDialog.dismiss(); - //如果创建群组时候没有选择人,那么size就是1 - createGroup(groupId, 1); - } - } else { - mLoadingDialog.dismiss(); - ToastUtil.shortToast(mContext, responseMsg); - } - } - }); + if (JGApplication.selectedUser != null && JGApplication.selectedUser.size() > 0) { + JGApplication.selectedUser.clear(); + } + JGApplication.selectedUser = mAdapter.getSelectedUser(); + Intent intent = new Intent(mContext, SelectCreateGroupTypeActivity.class); + startActivity(intent); break; } } - private void createGroup(long groupId, int groupMembersSize) { - Conversation groupConversation = JMessageClient.getGroupConversation(groupId); - if (groupConversation == null) { - groupConversation = Conversation.createGroupConversation(groupId); - EventBus.getDefault().post(new Event.Builder() - .setType(EventType.createConversation) - .setConversation(groupConversation) - .build()); - } - - Intent intent = new Intent(); - //设置跳转标志 - intent.putExtra("fromGroup", true); - intent.putExtra(JGApplication.CONV_TITLE, groupConversation.getTitle()); - intent.putExtra(JGApplication.MEMBERS_COUNT, groupMembersSize); - intent.putExtra(JGApplication.GROUP_ID, groupId); - intent.setClass(mContext, ChatActivity.class); - mContext.startActivity(intent); - finish(); - } - - @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { diff --git a/chatapp/src/main/java/jiguang/chat/activity/ForwardMsgActivity.java b/chatapp/src/main/java/jiguang/chat/activity/ForwardMsgActivity.java index 75aa7f9b..561f3e44 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/ForwardMsgActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/ForwardMsgActivity.java @@ -15,6 +15,7 @@ import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.content.TextContent; +import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.options.MessageSendingOptions; @@ -64,7 +65,7 @@ private void initView() { private void initData() { List conversationList = JMessageClient.getConversationList(); for (Conversation conv : conversationList) { - if (!conv.getTargetId().equals("feedback_Android")) { + if (!conv.getTargetId().equals("feedback_Android") && conv.getType() != ConversationType.chatroom) { forwardList.add(conv); } } diff --git a/chatapp/src/main/java/jiguang/chat/activity/FriendInfoActivity.java b/chatapp/src/main/java/jiguang/chat/activity/FriendInfoActivity.java index 16c09f81..207cb7fd 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/FriendInfoActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/FriendInfoActivity.java @@ -8,13 +8,14 @@ import com.activeandroid.query.Update; +import org.greenrobot.eventbus.EventBus; + import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import jiguang.chat.R; import jiguang.chat.application.JGApplication; import jiguang.chat.controller.FriendInfoController; @@ -60,7 +61,8 @@ protected void onCreate(Bundle savedInstanceState) { mTargetAppKey = JMessageClient.getMyInfo().getAppKey(); } mFriendInfoView.initModel(this); - mFriendInfoController = new FriendInfoController(mFriendInfoView, this); + int flags = getIntent().getFlags(); + mFriendInfoController = new FriendInfoController(flags, this); mFriendInfoView.setListeners(mFriendInfoController); mFriendInfoView.setOnChangeListener(mFriendInfoController); mIsFromContact = getIntent().getBooleanExtra("fromContact", false); @@ -164,8 +166,6 @@ public void startChatActivity() { .setConversation(conv) .build()); } - finish(); - } public UserInfo getUserInfo() { diff --git a/chatapp/src/main/java/jiguang/chat/activity/FriendListActivity.java b/chatapp/src/main/java/jiguang/chat/activity/FriendListActivity.java index 12034e26..459ca31b 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/FriendListActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/FriendListActivity.java @@ -17,12 +17,14 @@ import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.content.TextContent; +import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.options.MessageSendingOptions; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.adapter.FriendListAdapter; +import jiguang.chat.application.JGApplication; import jiguang.chat.database.FriendEntry; import jiguang.chat.database.UserEntry; import jiguang.chat.utils.DialogCreator; @@ -30,7 +32,7 @@ import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.pinyin.PinyinComparator; import jiguang.chat.utils.sidebar.SideBar; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** * Created by ${chenyn} on 2017/9/21. @@ -87,10 +89,26 @@ public void onClick(View v) { public void onItemClick(AdapterView parent, View view, int position, long id) { Object itemAtPosition = parent.getItemAtPosition(position); FriendEntry friendEntry = (FriendEntry) itemAtPosition; - if (getIntent().getBooleanExtra("isSingle", false)) { - setBusinessCard(friendEntry, JMessageClient.getSingleConversation(getIntent().getStringExtra("userId"))); - } else { - setBusinessCard(friendEntry, JMessageClient.getGroupConversation(getIntent().getLongExtra("groupId", 0))); + ConversationType convType = (ConversationType) getIntent().getSerializableExtra(JGApplication.CONV_TYPE); + String targetId = getIntent().getStringExtra(JGApplication.TARGET_ID); + String targetAppKey = getIntent().getStringExtra(JGApplication.TARGET_APP_KEY); + Conversation conv = null; + if (convType != null) { + switch (convType) { + case single: + conv = JMessageClient.getSingleConversation(targetId, targetAppKey); + break; + case group: + conv = JMessageClient.getGroupConversation(Long.valueOf(targetId)); + break; + case chatroom: + conv = JMessageClient.getChatRoomConversation(Long.valueOf(targetId)); + break; + default: + } + } + if (conv != null) { + setBusinessCard(friendEntry, conv); } } }); @@ -133,6 +151,9 @@ public void gotResult(int i, String s) { if (i == 0) { SharePreferenceManager.setIsOpen(true); Toast.makeText(FriendListActivity.this, "发送成功", Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(); + intent.putExtra(JGApplication.MSG_JSON, textMessage.toJson()); + FriendListActivity.this.setResult(RESULT_OK, intent); finish(); } else { HandleResponseCode.onHandle(FriendListActivity.this, i, false); diff --git a/chatapp/src/main/java/jiguang/chat/activity/FriendSettingActivity.java b/chatapp/src/main/java/jiguang/chat/activity/FriendSettingActivity.java index 9bc37dee..e5c9bb2a 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/FriendSettingActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/FriendSettingActivity.java @@ -10,6 +10,8 @@ import android.widget.RelativeLayout; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; import java.util.List; @@ -17,7 +19,6 @@ import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.application.JGApplication; diff --git a/chatapp/src/main/java/jiguang/chat/activity/GroupInfoActivity.java b/chatapp/src/main/java/jiguang/chat/activity/GroupInfoActivity.java new file mode 100644 index 00000000..58023a9f --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/GroupInfoActivity.java @@ -0,0 +1,112 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import jiguang.chat.R; +import jiguang.chat.utils.DialogCreator; + +/** + * Created by ${chenyn} on 2017/11/6. + */ + +public class GroupInfoActivity extends BaseActivity { + + private ImageView mIv_groupAvatar; + private TextView mTv_groupName; + private TextView mTv_groupId; + private TextView mTv_groupOwner; + private TextView mTv_groupMember; + private TextView mTv_groupDesc; + private Button mBtn_apply; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_group_info); + initTitle(true, true, "群资料", "", false, ""); + mIv_groupAvatar = (ImageView) findViewById(R.id.iv_groupAvatar); + mTv_groupName = (TextView) findViewById(R.id.tv_groupName); + mTv_groupId = (TextView) findViewById(R.id.tv_groupId); + mTv_groupOwner = (TextView) findViewById(R.id.tv_groupOwner); + mTv_groupMember = (TextView) findViewById(R.id.tv_groupMember); + mTv_groupDesc = (TextView) findViewById(R.id.tv_groupDesc); + mBtn_apply = (Button) findViewById(R.id.btn_apply); + + initData(); + } + + private void initData() { + Intent intent = getIntent(); + if (intent.getFlags() != 1) { + if (intent.getStringExtra("groupAvatar") != null) { + mIv_groupAvatar.setImageBitmap(BitmapFactory.decodeFile(intent.getStringExtra("groupAvatar"))); + } + mTv_groupName.setText(intent.getStringExtra("groupName")); + mTv_groupId.setText(intent.getLongExtra("groupId", 0) + ""); + mTv_groupOwner.setText(intent.getStringExtra("groupOwner")); + mTv_groupMember.setText(intent.getStringExtra("groupMember") + "人"); + if (TextUtils.isEmpty(intent.getStringExtra("groupDesc"))) { + mTv_groupDesc.setText("暂无描述"); + } else { + mTv_groupDesc.setText(intent.getStringExtra("groupDesc")); + } + mBtn_apply.setOnClickListener(v -> { + //申请入群 + Intent start = new Intent(GroupInfoActivity.this, VerificationGroupActivity.class); + //传群组id过去申请入群 + start.putExtra("openGroupID", intent.getLongExtra("groupId", 0)); + startActivity(start); + + }); + } else { + Dialog loadingDialog = DialogCreator.createLoadingDialog(GroupInfoActivity.this, "正在加载..."); + loadingDialog.show(); + String groupId = intent.getStringExtra("groupId"); + mBtn_apply.setVisibility(View.GONE); + JMessageClient.getGroupInfo(Long.parseLong(groupId), new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + loadingDialog.dismiss(); + if (i == 0) { + groupInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + mIv_groupAvatar.setImageBitmap(bitmap); + } else { + mIv_groupAvatar.setImageResource(R.drawable.group); + } + } + }); + + mTv_groupName.setText(groupInfo.getGroupName()); + mTv_groupId.setText(groupInfo.getGroupID() + ""); + mTv_groupOwner.setText(groupInfo.getGroupOwner()); + mTv_groupMember.setText(groupInfo.getGroupMembers().size() + ""); + if (!TextUtils.isEmpty(groupInfo.getGroupDescription())) { + mTv_groupDesc.setText(groupInfo.getGroupDescription()); + } else { + mTv_groupDesc.setText("暂无描述"); + } + } + } + }); + + } + + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/GroupMemberListActivity.java b/chatapp/src/main/java/jiguang/chat/activity/GroupMemberListActivity.java new file mode 100644 index 00000000..a494fbef --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/GroupMemberListActivity.java @@ -0,0 +1,129 @@ +package jiguang.chat.activity; + +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.util.Collections; +import java.util.List; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.model.Conversation; +import cn.jpush.im.android.api.model.GroupInfo; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; +import jiguang.chat.adapter.GroupMemberListAdapter; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.GroupMemberListComparator; +import jiguang.chat.utils.sidebar.SideBar; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; + +/** + * Created by ${chenyn} on 2017/11/3. + */ + +public class GroupMemberListActivity extends BaseActivity { + + private StickyListHeadersListView mGroup_listView; + private long mGroupId; + private List mMemberInfoList; + private GroupInfo mGroupInfo; + private LinearLayout mLl_groupSearch; + private ImageView mIv_ownerAvatar; + private TextView mTv_ownerName; + private TextView mTv_back; + private GroupMemberListAdapter mListAdapter; + private SideBar mSideBar; + private TextView mLetterHintTv; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_group_member_list); + initView(); + initData(); + } + + private void initData() { + mGroupId = getIntent().getLongExtra(JGApplication.GROUP_ID, 0); + + final Conversation conv = JMessageClient.getGroupConversation(mGroupId); + mGroupInfo = (GroupInfo) conv.getTargetInfo(); + mMemberInfoList = mGroupInfo.getGroupMembers(); + + //设置群主头像和名字 + JMessageClient.getUserInfo(mGroupInfo.getGroupOwner(), new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + if (i == 0) { + if (userInfo.getAvatarFile() != null) { + mIv_ownerAvatar.setImageBitmap(BitmapFactory.decodeFile(userInfo.getAvatarFile().getAbsolutePath())); + } + mTv_ownerName.setText(userInfo.getDisplayName()); + } + } + }); + + Collections.sort(mMemberInfoList, new GroupMemberListComparator()); + mListAdapter = new GroupMemberListAdapter(this, mMemberInfoList, mGroupId); + mGroup_listView.setAdapter(mListAdapter); + + mLl_groupSearch.setOnClickListener(v -> { + Intent intent = new Intent(GroupMemberListActivity.this, SearchGroupActivity.class); + intent.setFlags(1); + JGApplication.mSearchGroup = null; + JGApplication.mSearchGroup = mMemberInfoList; + startActivity(intent); + }); + + mTv_back.setOnClickListener(v -> finish()); + + mSideBar.setOnTouchingLetterChangedListener(s -> { + int position = mListAdapter.getSectionForLetter(s); + if (position != -1 && position < mListAdapter.getCount()) { + //设置滑动sidebar时listView滑动到指定位置 + mGroup_listView.setSelection(position); + } + }); + + //点击群成员列表,跳转详情界面 + mGroup_listView.setOnItemClickListener((parent, view, position, id) -> { + Object itemAtPosition = parent.getItemAtPosition(position); + if (itemAtPosition instanceof UserInfo) { + UserInfo info = (UserInfo) itemAtPosition; + Intent intent = new Intent(); + intent.setClass(GroupMemberListActivity.this, GroupUserInfoActivity.class); + intent.putExtra("groupID", mGroupId); + intent.putExtra("groupOwner", mGroupInfo.getGroupOwner()); + intent.putExtra("groupUserName", info.getUserName()); + startActivity(intent); + } + }); + } + + private void initView() { + mGroup_listView = (StickyListHeadersListView) findViewById(R.id.group_listView); + View headerOwner = View.inflate(this, R.layout.header_list_group_member, null); + mLl_groupSearch = headerOwner.findViewById(R.id.ll_groupSearch); + mIv_ownerAvatar = headerOwner.findViewById(R.id.iv_ownerAvatar); + mTv_ownerName = headerOwner.findViewById(R.id.tv_ownerName); + mTv_back = (TextView) findViewById(R.id.tv_back); + mSideBar = (SideBar) findViewById(R.id.sidebar); + mGroup_listView.addHeaderView(headerOwner); + mLetterHintTv = (TextView) findViewById(R.id.letter_hint_tv); + mSideBar.setTextView(mLetterHintTv); + mSideBar.bringToFront(); + } + + @Override + protected void onResume() { + super.onResume(); + mListAdapter.notifyDataSetChanged(); + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/GroupNotFriendActivity.java b/chatapp/src/main/java/jiguang/chat/activity/GroupNotFriendActivity.java index 6238b38f..2edf5afe 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/GroupNotFriendActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/GroupNotFriendActivity.java @@ -13,6 +13,8 @@ import android.widget.RelativeLayout; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; @@ -21,7 +23,6 @@ import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import jiguang.chat.R; import jiguang.chat.application.JGApplication; import jiguang.chat.entity.Event; diff --git a/chatapp/src/main/java/jiguang/chat/activity/GroupUserInfoActivity.java b/chatapp/src/main/java/jiguang/chat/activity/GroupUserInfoActivity.java new file mode 100644 index 00000000..5582ffe4 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/GroupUserInfoActivity.java @@ -0,0 +1,172 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import org.greenrobot.eventbus.EventBus; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.model.Conversation; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; +import jiguang.chat.application.JGApplication; +import jiguang.chat.entity.Event; +import jiguang.chat.entity.EventType; +import jiguang.chat.utils.DialogCreator; + +/** + * Created by ${chenyn} on 2017/11/27. + */ + +public class GroupUserInfoActivity extends BaseActivity { + + private ImageView mIv_more; + private ImageView mIv_userAvatar; + private TextView mTv_displayName; + private TextView mTv_sign; + private TextView mTv_userName; + private TextView mTv_nick; + private TextView mTv_gender; + private TextView mTv_birthday; + private TextView mTv_address; + private Button mBtn_send_message; + private String mUserName; + private String mAppKey = JMessageClient.getMyInfo().getAppKey(); // 默认使用本应用appkey + public static final String IS_FROM_GROUP = "is_from_group"; + private boolean isFromGroup = true; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.group_user_info); + isFromGroup = getIntent().getBooleanExtra(IS_FROM_GROUP, true); + + initView(); + initData(); + } + + private void initData() { + Dialog dialog = DialogCreator.createLoadingDialog(GroupUserInfoActivity.this, "正在加载..."); + dialog.show(); + JMessageClient.getUserInfo(mUserName, mAppKey, new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + dialog.dismiss(); + if (i == 0) { + userInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + mIv_userAvatar.setImageBitmap(bitmap); + } else { + mIv_userAvatar.setImageResource(R.drawable.jmui_head_icon); + } + } + }); + + mTv_displayName.setText(userInfo.getDisplayName()); + mTv_sign.setText(userInfo.getSignature()); + mTv_userName.setText(userInfo.getUserName()); + mTv_nick.setText(userInfo.getNickname() == null ? "" : userInfo.getNickname()); + UserInfo.Gender gender = userInfo.getGender(); + if (gender.equals(UserInfo.Gender.male)) { + mTv_gender.setText("男"); + } else if (gender.equals(UserInfo.Gender.female)) { + mTv_gender.setText("女"); + } else { + mTv_gender.setText("保密"); + } + mTv_birthday.setText(getBirthday(userInfo)); + mTv_address.setText(userInfo.getRegion()); + mBtn_send_message.setOnClickListener(v -> { + Intent intent = new Intent(); + intent.setClass(GroupUserInfoActivity.this, ChatActivity.class); + //创建会话 + intent.putExtra(JGApplication.TARGET_ID, userInfo.getUserName()); + intent.putExtra(JGApplication.TARGET_APP_KEY, userInfo.getAppKey()); + String notename = userInfo.getNotename(); + if (TextUtils.isEmpty(notename)) { + notename = userInfo.getNickname(); + if (TextUtils.isEmpty(notename)) { + notename = userInfo.getUserName(); + } + } + intent.putExtra(JGApplication.CONV_TITLE, notename); + Conversation conv = JMessageClient.getSingleConversation(userInfo.getUserName(), userInfo.getAppKey()); + //如果会话为空,使用EventBus通知会话列表添加新会话 + if (conv == null) { + conv = Conversation.createSingleConversation(userInfo.getUserName(), userInfo.getAppKey()); + EventBus.getDefault().post(new Event.Builder() + .setType(EventType.createConversation) + .setConversation(conv) + .build()); + } + startActivity(intent); + }); + } + } + }); + + mIv_more.setOnClickListener(v -> { + Intent intent = new Intent(GroupUserInfoActivity.this, SetGroupSilenceActivity.class); + long groupID = getIntent().getLongExtra("groupID", 0); + intent.putExtra("groupID", groupID); + intent.putExtra("userName", mUserName); + startActivity(intent); + }); + + } + + private void initView() { + if (isFromGroup) { + mUserName = getIntent().getStringExtra("groupUserName"); + } else { + mUserName = getIntent().getStringExtra(JGApplication.NAME); + mAppKey = getIntent().getStringExtra(JGApplication.TARGET_APP_KEY); + } + findViewById(R.id.return_btn).setOnClickListener(v -> finish()); + String groupOwner = getIntent().getStringExtra("groupOwner"); + mIv_more = (ImageView) findViewById(R.id.iv_more); + if (isFromGroup && groupOwner.equals(JMessageClient.getMyInfo().getUserName())) { + mIv_more.setVisibility(View.VISIBLE); + } else { + mIv_more.setVisibility(View.GONE); + } + + mIv_userAvatar = (ImageView) findViewById(R.id.iv_userAvatar); + mTv_displayName = (TextView) findViewById(R.id.tv_displayName); + mTv_sign = (TextView) findViewById(R.id.tv_sign); + mTv_userName = (TextView) findViewById(R.id.tv_userName); + mTv_nick = (TextView) findViewById(R.id.tv_nick); + mTv_gender = (TextView) findViewById(R.id.tv_gender); + mTv_birthday = (TextView) findViewById(R.id.tv_birthday); + mTv_address = (TextView) findViewById(R.id.tv_address); + mBtn_send_message = (Button) findViewById(R.id.btn_send_message); + if (!isFromGroup) { + mBtn_send_message.setVisibility(View.GONE); + } + } + + public String getBirthday(UserInfo info) { + long birthday = info.getBirthday(); + if (birthday == 0) { + return ""; + } else { + Date date = new Date(birthday); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.format(date); + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/MainActivity.java b/chatapp/src/main/java/jiguang/chat/activity/MainActivity.java index 343c077f..e5b116d9 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/MainActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/MainActivity.java @@ -1,9 +1,17 @@ package jiguang.chat.activity; +import android.Manifest; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.view.KeyEvent; +import android.widget.Toast; + +import com.yanzhenjie.permission.AndPermission; +import com.yanzhenjie.permission.PermissionListener; + +import java.util.ArrayList; +import java.util.List; import cn.jiguang.api.JCoreInterface; import jiguang.chat.R; @@ -13,13 +21,14 @@ public class MainActivity extends FragmentActivity { private MainController mMainController; private MainView mMainView; + private List permissions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - + requestPermission(); mMainView = (MainView) findViewById(R.id.main_view); mMainView.initModule(); mMainController = new MainController(mMainView, this); @@ -28,6 +37,34 @@ protected void onCreate(Bundle savedInstanceState) { mMainView.setOnPageChangeListener(mMainController); } + private void requestPermission() { + permissions = new ArrayList<>(); + permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE); + permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + permissions.add(Manifest.permission.CAMERA); + permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); + permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); + permissions.add(Manifest.permission.ACCESS_FINE_LOCATION); + permissions.add(Manifest.permission.ACCESS_WIFI_STATE); + permissions.add(Manifest.permission.RECORD_AUDIO); + if (AndPermission.hasPermission(this, permissions)) { + return; + }else { + AndPermission.with(this) + .requestCode(100) + .permission(Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.CAMERA, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_WIFI_STATE, + Manifest.permission.RECORD_AUDIO) + .callback(listener) + .start(); + } + } + public FragmentManager getSupportFragmentManger() { return getSupportFragmentManager(); } @@ -53,4 +90,33 @@ protected void onDestroy() { public boolean onKeyDown(int keyCode, KeyEvent event) { return keyCode == KeyEvent.KEYCODE_BACK; } + + + private PermissionListener listener = new PermissionListener() { + @Override + public void onSucceed(int requestCode, List grantedPermissions) { + // Successfully. + if(requestCode == 100) { + Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onFailed(int requestCode, List deniedPermissions) { + // Failure. + + } + }; + +// private RationaleListener rationaleListener = (requestCode, rationale) -> { +// AlertDialog.newBuilder(this) +// .setMessage("正常使用JChat需要您打开相关权限.") +// .setPositiveButton("是", (dialog, which) -> { +// rationale.resume(); +// }) +// .setNegativeButton("否", (dialog, which) -> { +// rationale.cancel(); +// }).show(); +// }; + } diff --git a/chatapp/src/main/java/jiguang/chat/activity/NickSignActivity.java b/chatapp/src/main/java/jiguang/chat/activity/NickSignActivity.java index 78f892ee..deae2932 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/NickSignActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/NickSignActivity.java @@ -1,6 +1,7 @@ package jiguang.chat.activity; import android.content.Intent; +import android.graphics.Color; import android.os.Bundle; import android.text.Editable; import android.text.InputFilter; @@ -19,15 +20,19 @@ */ public class NickSignActivity extends BaseActivity { + public static final String TYPE = "type"; + public static final String COUNT = "count"; + public static final String DESC = "desc"; + + public enum Type { + GROUP_NAME, GROUP_DESC, PERSON_SIGN, PERSON_NICK, CHAT_ROOM_NAME, CHAT_ROOM_DESC; + } private EditText mEd_sign; + private TextView mTv_title; private TextView mTv_count; private LinearLayout mLl_nickSign; - private static final int SIGN_COUNT = 250; - private static final int NICK_COUNT = 64; - private static final int GROUP_DESC = 250; - private static final int GROUP_NAME = 64; private Button mJmui_commit_btn; @Override @@ -37,43 +42,78 @@ protected void onCreate(Bundle savedInstanceState) { initView(); Intent intent = getIntent(); - if (intent.getFlags() == PersonalActivity.FLAGS_SIGN) { - initViewSign("个性签名", SIGN_COUNT); - initData(SIGN_COUNT); - } else if (intent.getFlags() == PersonalActivity.FLAGS_NICK) { - initViewNick("修改昵称", NICK_COUNT); - initData(NICK_COUNT); - } else if (intent.getFlags() == ChatDetailActivity.FLAGS_GROUP_DESC) { - initViewSign("群描述", GROUP_DESC); - initData(GROUP_DESC); - } else if (intent.getFlags() == ChatDetailActivity.FLAGS_GROUP_NAME) { - initViewNick("群名称", GROUP_NAME); - initData(GROUP_NAME); + Type type = (Type) intent.getSerializableExtra(TYPE); + int count = intent.getIntExtra(COUNT, 0); + switch (type) { + case PERSON_SIGN: + initViewSign("个性签名", count); + break; + case PERSON_NICK: + initViewNick("修改昵称", count); + break; + case GROUP_DESC: + initViewSign("群描述", count); + break; + case GROUP_NAME: + initViewNick("群名称", count); + break; + case CHAT_ROOM_NAME: + case CHAT_ROOM_DESC: + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mEd_sign.getLayoutParams(); + layoutParams.leftMargin = (int) (10 * mDensity); + layoutParams.rightMargin = (int) (10 * mDensity); + layoutParams.topMargin = (int) (5 * mDensity); + if (type == Type.CHAT_ROOM_NAME) { + initViewNick("聊天室名称", count); + mTv_title.setText("聊天室名称"); + layoutParams.bottomMargin = (int) (20 * mDensity); + } else { + initViewSign("聊天室介绍", count); + mTv_title.setText("聊天室介绍"); + layoutParams.bottomMargin = (int) (30 * mDensity); + } + mTv_count.setVisibility(View.GONE); + mTv_title.setVisibility(View.VISIBLE); + mEd_sign.setFocusable(false); + mEd_sign.setFocusableInTouchMode(false); + mEd_sign.setBackgroundColor(Color.parseColor("#FFE8EDF3")); + mEd_sign.setLayoutParams(layoutParams); + mLl_nickSign.setBackgroundColor(Color.WHITE); + mJmui_commit_btn.setVisibility(View.GONE); + break; + + default: + break; } - initListener(intent.getFlags()); + initData(count); + initListener(type); } - private void initListener(final int flags) { + private void initListener(Type type) { mJmui_commit_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String sign = mEd_sign.getText().toString(); Intent intent = new Intent(); - if (flags == PersonalActivity.FLAGS_NICK) {//3 - intent.putExtra(PersonalActivity.NICK_NAME_KEY, sign); - setResult(PersonalActivity.NICK_NAME, intent);//4 - } else if (flags == PersonalActivity.FLAGS_SIGN) {//2 - intent.putExtra(PersonalActivity.SIGN_KEY, sign); - setResult(PersonalActivity.SIGN, intent);//1 - - } else if (flags == ChatDetailActivity.FLAGS_GROUP_DESC) {//71 - intent.putExtra(ChatDetailActivity.GROUP_DESC_KEY, sign); - setResult(ChatDetailActivity.GROUP_DESC, intent);//70 - - } else if (flags == ChatDetailActivity.FLAGS_GROUP_NAME) {//73 - intent.putExtra(ChatDetailActivity.GROUP_NAME_KEY, sign); - setResult(ChatDetailActivity.GROUP_NAME, intent);//72 - + switch (type) { + case PERSON_NICK: + intent.putExtra(PersonalActivity.NICK_NAME_KEY, sign); + setResult(PersonalActivity.NICK_NAME, intent);//4 + break; + case PERSON_SIGN: + intent.putExtra(PersonalActivity.SIGN_KEY, sign); + setResult(PersonalActivity.SIGN, intent);//1 + break; + case GROUP_DESC: + intent.putExtra(ChatDetailActivity.GROUP_DESC_KEY, sign); + setResult(ChatDetailActivity.GROUP_DESC, intent);//70 + break; + case GROUP_NAME: + intent.putExtra(ChatDetailActivity.GROUP_NAME_KEY, sign); + setResult(ChatDetailActivity.GROUP_NAME, intent);//72 + break; + default: + break; } //做更新动作 finish(); @@ -108,20 +148,8 @@ private void initView() { mLl_nickSign = (LinearLayout) findViewById(R.id.ll_nickSign); mTv_count = (TextView) findViewById(R.id.tv_count); mJmui_commit_btn = (Button) findViewById(R.id.jmui_commit_btn); - - if (getIntent().getStringExtra("group_name") != null) { - mEd_sign.setText(getIntent().getStringExtra("group_name")); - } - if (getIntent().getStringExtra("group_desc") != null) { - mEd_sign.setText(getIntent().getStringExtra("group_desc")); - } - if (getIntent().getStringExtra("old_nick") != null) { - mEd_sign.setText(getIntent().getStringExtra("old_nick")); - } - if (getIntent().getStringExtra("old_sign") != null) { - mEd_sign.setText(getIntent().getStringExtra("old_sign")); - } - + mTv_title = (TextView) findViewById(R.id.tv_title); + mEd_sign.setText(getIntent().getStringExtra(DESC)); mEd_sign.setSelection(mEd_sign.getText().length()); } @@ -135,11 +163,11 @@ private void initViewSign(String str, int flag) { mTv_count.setText(flag - length + ""); } - private void initViewNick(String str, int flag) { + private void initViewNick(String str, int count) { initTitle(true, true, str, "", true, "完成"); - mEd_sign.setFilters(new InputFilter[] {new MyLengthFilter(flag)}); + mEd_sign.setFilters(new InputFilter[] {new MyLengthFilter(count)}); int length = mEd_sign.getText().toString().getBytes().length; - mTv_count.setText(flag - length + ""); + mTv_count.setText(count - length + ""); int width = LinearLayout.LayoutParams.MATCH_PARENT; diff --git a/chatapp/src/main/java/jiguang/chat/activity/PersonalActivity.java b/chatapp/src/main/java/jiguang/chat/activity/PersonalActivity.java index 856223c0..be8862e9 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/PersonalActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/PersonalActivity.java @@ -40,13 +40,14 @@ public class PersonalActivity extends BaseActivity implements SelectAddressInterface, View.OnClickListener { public static final int SIGN = 1; - public static final int FLAGS_SIGN = 2; public static final String SIGN_KEY = "sign_key"; public static final int NICK_NAME = 4; - public static final int FLAGS_NICK = 3; public static final String NICK_NAME_KEY = "nick_name_key"; + private static final int SIGN_COUNT = 250; + private static final int NICK_COUNT = 64; + private RelativeLayout mRl_cityChoose; private TextView mTv_city; private SelectAddressDialog dialog; @@ -190,14 +191,16 @@ public void onClick(View v) { break; case R.id.rl_nickName: //昵称 - intent.setFlags(FLAGS_NICK); - intent.putExtra("old_nick", mMyInfo.getNickname()); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.PERSON_NICK); + intent.putExtra(NickSignActivity.COUNT, NICK_COUNT); + intent.putExtra(NickSignActivity.DESC, mMyInfo.getNickname()); startActivityForResult(intent, NICK_NAME); break; case R.id.sign: //签名 - intent.setFlags(FLAGS_SIGN); - intent.putExtra("old_sign", mMyInfo.getSignature()); + intent.putExtra(NickSignActivity.TYPE, NickSignActivity.Type.PERSON_SIGN); + intent.putExtra(NickSignActivity.COUNT, SIGN_COUNT); + intent.putExtra(NickSignActivity.DESC, mMyInfo.getSignature()); startActivityForResult(intent, SIGN); break; case R.id.rl_gender: diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchAddOpenGroupActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchAddOpenGroupActivity.java new file mode 100644 index 00000000..49087609 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchAddOpenGroupActivity.java @@ -0,0 +1,139 @@ +package jiguang.chat.activity; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import jiguang.chat.R; +import jiguang.chat.utils.photochoose.SelectableRoundedImageView; + +/** + * Created by ${chenyn} on 2017/11/6. + */ + +public class SearchAddOpenGroupActivity extends BaseActivity { + + private EditText mEt_searchGroup; + private Button mBtn_search; + private ImageView mIv_clear; + private LinearLayout mLl_group; + private SelectableRoundedImageView mSearch_group_avatar; + private TextView mTv_groupName; + private TextView mTv_groupID; + private TextView mTv_groupDesc; + private GroupInfo mGroupInfo; + private TextView mTv_searchResult; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_search_add_open_group); + + mEt_searchGroup = (EditText) findViewById(R.id.et_searchGroup); + mBtn_search = (Button) findViewById(R.id.btn_search); + mIv_clear = (ImageView) findViewById(R.id.iv_clear); + + mLl_group = (LinearLayout) findViewById(R.id.ll_group); + mSearch_group_avatar = (SelectableRoundedImageView) findViewById(R.id.search_group_avatar); + mTv_groupName = (TextView) findViewById(R.id.tv_groupName); + mTv_groupID = (TextView) findViewById(R.id.tv_groupID); + mTv_groupDesc = (TextView) findViewById(R.id.tv_groupDesc); + mTv_searchResult = (TextView) findViewById(R.id.tv_searchResult); + + initTitle(true, true, "加入公开群", "", false, ""); + + initData(); + } + + private void initData() { + mEt_searchGroup.addTextChangedListener(new TextChange()); + mIv_clear.setOnClickListener(v -> mEt_searchGroup.setText("")); + ProgressDialog dialog = new ProgressDialog(SearchAddOpenGroupActivity.this); + dialog.setMessage("正在加载..."); + dialog.setCanceledOnTouchOutside(false); + mBtn_search.setOnClickListener(v -> { + if (mEt_searchGroup.getText() != null) { + String groupId = mEt_searchGroup.getText().toString().trim(); + JMessageClient.getGroupInfo(Long.parseLong(groupId), new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + dialog.dismiss(); + if (i == 0 && (groupInfo.getGroupFlag() == 2)) { + mGroupInfo = groupInfo; + mTv_searchResult.setVisibility(View.GONE); + mLl_group.setVisibility(View.VISIBLE); + + if (groupInfo.getAvatarFile() != null) { + mSearch_group_avatar.setImageBitmap(BitmapFactory.decodeFile(groupInfo.getAvatarFile().getAbsolutePath())); + } else { + mSearch_group_avatar.setImageResource(R.drawable.jmui_head_icon); + } + mTv_groupName.setText(groupInfo.getGroupName()); + mTv_groupID.setText(groupInfo.getGroupID() + ""); + mTv_groupDesc.setText(groupInfo.getGroupDescription()); + } else { + mTv_searchResult.setVisibility(View.VISIBLE); + mLl_group.setVisibility(View.GONE); + } + } + }); + } else { + Toast.makeText(SearchAddOpenGroupActivity.this, "请输入群组id", Toast.LENGTH_SHORT).show(); + } + }); + + mLl_group.setOnClickListener(v -> { + //申请加入群 + Intent intent = new Intent(SearchAddOpenGroupActivity.this, GroupInfoActivity.class); + if (mGroupInfo != null) { + if (mGroupInfo.getAvatarFile() != null) { + intent.putExtra("groupAvatar", mGroupInfo.getAvatarFile().getAbsolutePath()); + } + intent.putExtra("groupName", mGroupInfo.getGroupName()); + intent.putExtra("groupId", mGroupInfo.getGroupID()); + intent.putExtra("groupOwner", mGroupInfo.getGroupOwner()); + intent.putExtra("groupMember", mGroupInfo.getGroupMembers().size() + ""); + intent.putExtra("groupDesc", mGroupInfo.getGroupDescription()); + startActivity(intent); + } + }); + } + + private class TextChange implements TextWatcher { + + @Override + public void afterTextChanged(Editable arg0) { + } + + @Override + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, + int arg3) { + } + + @Override + public void onTextChanged(CharSequence cs, int start, int before, + int count) { + boolean feedback = mEt_searchGroup.getText().length() > 0; + if (feedback) { + mIv_clear.setVisibility(View.VISIBLE); + mBtn_search.setEnabled(true); + } else { + mIv_clear.setVisibility(View.GONE); + mBtn_search.setEnabled(false); + } + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchChatRoomActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchChatRoomActivity.java new file mode 100644 index 00000000..4dca1887 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchChatRoomActivity.java @@ -0,0 +1,153 @@ +package jiguang.chat.activity; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Collections; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.model.ChatRoomInfo; +import jiguang.chat.R; +import jiguang.chat.utils.CommonUtils; + +/** + * Created by ${chenyn} on 2017/11/9. + */ + +public class SearchChatRoomActivity extends BaseActivity { + + private LinearLayout mLl_chatRoomItem; + private ImageView mIv_chatRoomAvatar; + private TextView mTv_chatRoomName; + private TextView mTv_chatRoomDesc; + private EditText mSearchEditText; + private LinearLayout mAc_iv_press_back; + private TextView mTv_search; + private long mRoomID; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_search_chat_room); + + initView(); + initData(); + } + + @SuppressLint("ClickableViewAccessibility") + private void initData() { + //清空EditText + mSearchEditText.setOnTouchListener((v, event) -> { + final int DRAWABLE_RIGHT = 2; + if (event.getAction() == MotionEvent.ACTION_UP) { + if (event.getRawX() >= (mSearchEditText.getRight() - 2 * mSearchEditText.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) { + mSearchEditText.setText(""); + mSearchEditText.clearFocus(); + mLl_chatRoomItem.setVisibility(View.GONE); + return true; + } + } + return false; + }); + + + mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_UNSPECIFIED) { + + String keytag = mSearchEditText.getText().toString().trim(); + + if (TextUtils.isEmpty(keytag)) { + Toast.makeText(SearchChatRoomActivity.this, "请输入聊天室ID", Toast.LENGTH_SHORT).show(); + } else { + String roomId = mSearchEditText.getText().toString().trim(); + try { + long id = Long.parseLong(roomId); + ChatRoomManager.getChatRoomInfos(Collections.singleton(id), new RequestCallback>() { + @Override + public void gotResult(int i, String s, List chatRoomInfos) { + if (i == 0) { + mRoomID = chatRoomInfos.get(0).getRoomID(); + mLl_chatRoomItem.setVisibility(View.VISIBLE); + mTv_chatRoomDesc.setText(chatRoomInfos.get(0).getDescription()); + mTv_chatRoomName.setText(chatRoomInfos.get(0).getName()); + }else { + mLl_chatRoomItem.setVisibility(View.GONE); + Toast.makeText(SearchChatRoomActivity.this, "搜索的聊天室不存在", Toast.LENGTH_SHORT).show(); + } + } + }); + } catch (NumberFormatException e) { + Toast.makeText(SearchChatRoomActivity.this, "搜索的聊天室不存在", Toast.LENGTH_SHORT).show(); + } + } + } + return true; + } + }); + + mAc_iv_press_back.setOnClickListener(v -> { + finish(); + CommonUtils.hideKeyboard(SearchChatRoomActivity.this); + }); + mTv_search.setOnClickListener(v -> { + if (!TextUtils.isEmpty(mSearchEditText.getText())) { + String roomId = mSearchEditText.getText().toString().trim(); + try { + long id = Long.parseLong(roomId); + ChatRoomManager.getChatRoomInfos(Collections.singleton(id), new RequestCallback>() { + @Override + public void gotResult(int i, String s, List chatRoomInfos) { + if (i == 0) { + mRoomID = chatRoomInfos.get(0).getRoomID(); + mLl_chatRoomItem.setVisibility(View.VISIBLE); + mTv_chatRoomDesc.setText(chatRoomInfos.get(0).getDescription()); + mTv_chatRoomName.setText(chatRoomInfos.get(0).getName()); + }else { + mLl_chatRoomItem.setVisibility(View.GONE); + Toast.makeText(SearchChatRoomActivity.this, "搜索的聊天室不存在", Toast.LENGTH_SHORT).show(); + } + } + }); + } catch (NumberFormatException e) { + Toast.makeText(SearchChatRoomActivity.this, "搜索的聊天室不存在", Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(SearchChatRoomActivity.this, "请输入聊天室ID", Toast.LENGTH_SHORT).show(); + } + }); + + mLl_chatRoomItem.setOnClickListener(v -> { + Intent intent = new Intent(SearchChatRoomActivity.this, ChatRoomDetailActivity.class); + intent.putExtra("chatRoomId", mRoomID); + startActivity(intent); + }); + + } + + private void initView() { + mLl_chatRoomItem = (LinearLayout) findViewById(R.id.ll_chatRoomItem); + mIv_chatRoomAvatar = (ImageView) findViewById(R.id.iv_chatRoomAvatar); + mTv_chatRoomName = (TextView) findViewById(R.id.tv_chatRoomName); + mTv_chatRoomDesc = (TextView) findViewById(R.id.tv_chatRoomDesc); + mTv_search = (TextView) findViewById(R.id.tv_search); + + mAc_iv_press_back = (LinearLayout) findViewById(R.id.ac_iv_press_back); + mSearchEditText = (EditText) findViewById(R.id.ac_et_search); + } + +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchContactsActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchContactsActivity.java index b8b975f6..408c4ccb 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/SearchContactsActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchContactsActivity.java @@ -1,5 +1,6 @@ package jiguang.chat.activity; +import android.annotation.SuppressLint; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -33,6 +34,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -50,7 +53,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.application.JGApplication; @@ -156,6 +158,7 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + @SuppressLint("StaticFieldLeak") @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mFilterFriendList = new ArrayList<>(); @@ -175,14 +178,10 @@ protected SearchResult doInBackground(String... params) { protected void onPostExecute(SearchResult searchResult) { if (searchResult.getFilterStr().equals(mFilterString)) { List friendList = searchResult.getFriendList(); - for (UserInfo friend : friendList) { - mFilterFriendList.add(friend); - } + mFilterFriendList.addAll(friendList); List groupList = searchResult.getGroupList(); - for (GroupInfo group : groupList) { - mFilterGroupList.add(group); - } + mFilterGroupList.addAll(groupList); if (mFilterFriendList.size() == 0 && mFilterGroupList.size() == 0) { if (mFilterString.equals("")) { diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchForChatRoomActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchForChatRoomActivity.java new file mode 100644 index 00000000..04746eef --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchForChatRoomActivity.java @@ -0,0 +1,187 @@ +package jiguang.chat.activity; + +import android.content.Context; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.model.UserInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.application.JGApplication; +import jiguang.chat.model.InfoModel; +import jiguang.chat.utils.ToastUtil; +import jiguang.chat.utils.dialog.LoadDialog; +import jiguang.chat.utils.photochoose.SelectableRoundedImageView; + +public class SearchForChatRoomActivity extends BaseActivity implements View.OnClickListener { + private EditText mEtSearchUser; + private Button mBtnSearch; + private Button mSearchAddBtn; + private TextView mTvAddNot; + private LinearLayout mSearch_result; + private SelectableRoundedImageView mSearch_header; + private TextView mSearchName; + private ImageView mIvClear; + private long roomId; + private List keeperList = new ArrayList<>(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_search_for_chat_room); + roomId = getIntent().getLongExtra(JGApplication.ROOM_ID, 0); + mEtSearchUser = (EditText) findViewById(R.id.et_searchUser); + mEtSearchUser.addTextChangedListener(new TextChange()); + mBtnSearch = (Button) findViewById(R.id.btn_search); + mBtnSearch.setOnClickListener(this); + mSearchAddBtn = (Button) findViewById(R.id.search_addBtn); + mSearchAddBtn.setOnClickListener(this); + mTvAddNot = (TextView) findViewById(R.id.search_addNot); + mSearch_result = (LinearLayout) findViewById(R.id.search_result); + mSearch_header = (SelectableRoundedImageView) findViewById(R.id.search_header); + mSearchName = (TextView) findViewById(R.id.search_name); + mIvClear = (ImageView) findViewById(R.id.iv_clear); + mIvClear.setOnClickListener(this); + + initTitle(true, true, "添加管理员", "", false, ""); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_search: + hintKbTwo(); + String searchUserName = mEtSearchUser.getText().toString(); + if (!TextUtils.isEmpty(searchUserName)) { + LoadDialog.show(this); + ChatRoomManager.getChatRoomAdminList(roomId, new RequestCallback>() { + @Override + public void gotResult(int responseCode, String responseMessage, List userInfos) { + if (responseCode == 0) { + keeperList.clear(); + for (UserInfo userInfo : userInfos) { + keeperList.add(userInfo.getUserID()); + } + } + JMessageClient.getUserInfo(searchUserName, new GetUserInfoCallback() { + @Override + public void gotResult(int responseCode, String responseMessage, UserInfo info) { + LoadDialog.dismiss(SearchForChatRoomActivity.this); + if (responseCode == 0) { + InfoModel.getInstance().friendInfo = info; + mSearch_result.setVisibility(View.VISIBLE); + //已经是管理员则不显示"添加"按钮 + if (keeperList.contains(info.getUserID())) { + mSearchAddBtn.setVisibility(View.GONE); + mTvAddNot.setVisibility(View.VISIBLE); + mTvAddNot.setText("已添加"); + } else { + mSearchAddBtn.setVisibility(View.VISIBLE); + mTvAddNot.setVisibility(View.GONE); + } + File avatarFile = info.getAvatarFile(); + if (avatarFile != null) { + mSearch_header.setImageBitmap(BitmapFactory.decodeFile(avatarFile.getAbsolutePath())); + } else { + mSearch_header.setImageResource(R.drawable.rc_default_portrait); + } + mSearchName.setText(info.getDisplayName()); + } else { + ToastUtil.shortToast(SearchForChatRoomActivity.this, "该用户不存在"); + mSearch_result.setVisibility(View.GONE); + } + } + }); + } + }); + } + break; + case R.id.search_addBtn: + ChatRoomManager.addChatRoomAdmin(roomId, Collections.singletonList(InfoModel.getInstance().friendInfo), new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + ToastUtil.shortToast(SearchForChatRoomActivity.this, "添加成功"); + } else { + handleErrorCode(i); + } + + mSearch_result.setVisibility(View.GONE); + } + }); + break; + case R.id.iv_clear: + mEtSearchUser.setText(""); + break; + default: + + } + } + + private void handleErrorCode(int code) { + String result = "添加失败,code:" + code; + switch (code) { + case 7130004: + result = "添加失败,管理员人数已达上限"; + break; + case 7130006: + result = "添加失败,用户不在聊天室中"; + break; + default: + } + ToastUtil.shortToast(SearchForChatRoomActivity.this, result); + } + + private class TextChange implements TextWatcher { + + @Override + public void afterTextChanged(Editable arg0) { + } + + @Override + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, + int arg3) { + } + + @Override + public void onTextChanged(CharSequence cs, int start, int before, + int count) { + boolean feedback = mEtSearchUser.getText().length() > 0; + if (feedback) { + mIvClear.setVisibility(View.VISIBLE); + mBtnSearch.setEnabled(true); + } else { + mIvClear.setVisibility(View.GONE); + mBtnSearch.setEnabled(false); + } + } + } + + private void hintKbTwo() { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm.isActive() && getCurrentFocus() != null) { + if (getCurrentFocus().getWindowToken() != null) { + imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchFriendDetailActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchFriendDetailActivity.java index 49baa900..8aa62fcd 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/SearchFriendDetailActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchFriendDetailActivity.java @@ -10,6 +10,8 @@ import android.widget.ImageView; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import java.text.SimpleDateFormat; import java.util.Date; @@ -18,7 +20,6 @@ import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.application.JGApplication; diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchGroupActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchGroupActivity.java index 4889ffc2..d928dcef 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/SearchGroupActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchGroupActivity.java @@ -320,8 +320,14 @@ public void onItemClick(AdapterView parent, View view, int position, long id) UserInfo info = ((UserInfo) itemAtPosition); if (info.isFriend()) { intent.setClass(SearchGroupActivity.this, FriendInfoActivity.class); + if (getIntent().getFlags() == 1) {//设置是群成员点击过去的详情界面 + intent.setFlags(1); + } intent.putExtra("fromSearch", true); } else { + if (getIntent().getFlags() == 1) { + intent.setFlags(1); + } intent.setClass(SearchGroupActivity.this, GroupNotFriendActivity.class); } intent.putExtra(JGApplication.TARGET_ID, info.getUserName()); diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchMoreFriendsActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchMoreFriendsActivity.java index e4cf868b..170f42be 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/SearchMoreFriendsActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchMoreFriendsActivity.java @@ -24,6 +24,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; @@ -38,7 +40,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.application.JGApplication; diff --git a/chatapp/src/main/java/jiguang/chat/activity/SearchMoreGroupActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SearchMoreGroupActivity.java index 1f28bdb6..cf6fae4c 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/SearchMoreGroupActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/SearchMoreGroupActivity.java @@ -21,6 +21,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; @@ -34,7 +36,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.adapter.SearchGroupListAdapter; diff --git a/chatapp/src/main/java/jiguang/chat/activity/SelectCreateGroupTypeActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SelectCreateGroupTypeActivity.java new file mode 100644 index 00000000..9502d6f4 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SelectCreateGroupTypeActivity.java @@ -0,0 +1,265 @@ +package jiguang.chat.activity; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import org.greenrobot.eventbus.EventBus; + +import java.io.File; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.CreateGroupCallback; +import cn.jpush.im.android.api.model.Conversation; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.application.JGApplication; +import jiguang.chat.entity.Event; +import jiguang.chat.entity.EventType; +import jiguang.chat.utils.DialogCreator; +import jiguang.chat.utils.ToastUtil; +import jiguang.chat.utils.photochoose.ChoosePhoto; +import jiguang.chat.utils.photochoose.PhotoUtils; + +/** + * Created by ${chenyn} on 2017/11/21. + */ + +@SuppressLint("Registered") +public class SelectCreateGroupTypeActivity extends BaseActivity implements TextWatcher { + + private Dialog mLoadingDialog; + private ImageView mIv_groupAvatar; + private EditText mEt_groupName; + private LinearLayout mLl_groupType; + private TextView mTv_groupSelect; + private TextView tvInGroupDesc; + private Button mBtn_createGroup; + private ChoosePhoto mChoosePhoto; + private File avatarFile; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_select_create_group_type); + initTitle(true, true, "发起群聊", "", false, ""); + JGApplication.groupAvatarPath = null;//清空头像信息 + + initView(); + initData(); + } + + private void initData() { + mEt_groupName.addTextChangedListener(this); + mLl_groupType.setOnClickListener(v -> showDialog()); + mBtn_createGroup.setOnClickListener(v -> { + mLoadingDialog = DialogCreator.createLoadingDialog(this, getString(R.string.creating_hint)); + mLoadingDialog.show(); + if (JGApplication.groupAvatarPath != null) { + avatarFile = new File(JGApplication.groupAvatarPath); + } else { + avatarFile = null; + } + + if (mTv_groupSelect.getText().toString().equals("私有群")) { + //创建私有群 + JMessageClient.createGroup(mEt_groupName.getText().toString(), "", avatarFile, "", new CreateGroupCallback() { + @Override + public void gotResult(int responseCode, String responseMsg, final long groupId) { + if (responseCode == 0) { + if (JGApplication.selectedUser.size() > 0) { + JMessageClient.addGroupMembers(groupId, JGApplication.selectedUser, new BasicCallback() { + @Override + public void gotResult(int responseCode, String responseMessage) { + mLoadingDialog.dismiss(); + if (responseCode == 0) { + //如果创建群组时添加了人,那么就在size基础上加上自己 + createGroup(groupId, JGApplication.selectedUser.size() + 1); + } else if (responseCode == 810007) { + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, "不能添加自己"); + } else { + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, "添加失败"); + } + } + }); + } else { + mLoadingDialog.dismiss(); + //如果创建群组时候没有选择人,那么size就是1 + createGroup(groupId, 1); + } + Toast.makeText(SelectCreateGroupTypeActivity.this, "创建成功", Toast.LENGTH_SHORT).show(); + } else { + mLoadingDialog.dismiss(); + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, responseMsg); + } + } + }); + } else { + JMessageClient.createPublicGroup(mEt_groupName.getText().toString(), "", avatarFile, "", new CreateGroupCallback() { + @Override + public void gotResult(int responseCode, String responseMsg, final long groupId) { + if (responseCode == 0) { + if (JGApplication.selectedUser.size() > 0) { + JMessageClient.addGroupMembers(groupId, JGApplication.selectedUser, new BasicCallback() { + @Override + public void gotResult(int responseCode, String responseMessage) { + mLoadingDialog.dismiss(); + if (responseCode == 0) { + //如果创建群组时添加了人,那么就在size基础上加上自己 + createGroup(groupId, JGApplication.selectedUser.size() + 1); + } else if (responseCode == 810007) { + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, "不能添加自己"); + } else { + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, "添加失败"); + } + } + }); + } else { + mLoadingDialog.dismiss(); + //如果创建群组时候没有选择人,那么size就是1 + createGroup(groupId, 1); + } + Toast.makeText(SelectCreateGroupTypeActivity.this, "创建成功", Toast.LENGTH_SHORT).show(); + } else { + mLoadingDialog.dismiss(); + ToastUtil.shortToast(SelectCreateGroupTypeActivity.this, responseMsg); + } + } + }); + } + }); + + + mIv_groupAvatar.setOnClickListener(v -> { + mChoosePhoto = new ChoosePhoto(); + mChoosePhoto.getCreateGroupAvatar(mIv_groupAvatar); + mChoosePhoto.showPhotoDialog(SelectCreateGroupTypeActivity.this); + }); + + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case PhotoUtils.INTENT_CROP: + case PhotoUtils.INTENT_TAKE: + case PhotoUtils.INTENT_SELECT: + mChoosePhoto.photoUtils.onActivityResult(SelectCreateGroupTypeActivity.this, requestCode, resultCode, data); + break; + } + } + + private void createGroup(long groupId, int groupMembersSize) { + Conversation groupConversation = JMessageClient.getGroupConversation(groupId); + if (groupConversation == null) { + groupConversation = Conversation.createGroupConversation(groupId); + EventBus.getDefault().post(new Event.Builder() + .setType(EventType.createConversation) + .setConversation(groupConversation) + .build()); + } + + Intent intent = new Intent(); + //设置跳转标志 + intent.putExtra("fromGroup", true); + intent.putExtra(JGApplication.CONV_TITLE, groupConversation.getTitle()); + intent.putExtra(JGApplication.MEMBERS_COUNT, groupMembersSize); + intent.putExtra(JGApplication.GROUP_ID, groupId); + intent.setClass(SelectCreateGroupTypeActivity.this, ChatActivity.class); + startActivity(intent); + finish(); + } + + private void initView() { + mIv_groupAvatar = (ImageView) findViewById(R.id.iv_groupAvatar); + mEt_groupName = (EditText) findViewById(R.id.et_groupName); + mLl_groupType = (LinearLayout) findViewById(R.id.ll_groupType); + mTv_groupSelect = (TextView) findViewById(R.id.tv_groupSelect); + tvInGroupDesc = (TextView) findViewById(R.id.tvInGroupDesc); + mBtn_createGroup = (Button) findViewById(R.id.btn_createGroup); + + mBtn_createGroup.setClickable(false); + mBtn_createGroup.setEnabled(false); + } + + + public void showDialog() { + final Dialog genderDialog = new Dialog(this, R.style.jmui_default_dialog_style); + LayoutInflater inflater = LayoutInflater.from(this); + View view = inflater.inflate(R.layout.dialog_set_sex, null); + genderDialog.setContentView(view); + Window window = genderDialog.getWindow(); + window.setWindowAnimations(R.style.mystyle); // 添加动画 + window.setGravity(Gravity.BOTTOM); + window.setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + genderDialog.show(); + genderDialog.setCanceledOnTouchOutside(true); + Button man = (Button) view.findViewById(R.id.man_rl); + Button woman = (Button) view.findViewById(R.id.woman_rl); + Button secrecy = (Button) view.findViewById(R.id.rl_secrecy); + man.setText("私有群"); + woman.setText("公开群"); + secrecy.setText("取消"); + + View.OnClickListener listener = v -> { + switch (v.getId()) { + case R.id.man_rl: + mTv_groupSelect.setText("私有群"); + tvInGroupDesc.setText("只能通过群成员邀请入群,无需审核"); + genderDialog.dismiss(); + break; + case R.id.woman_rl: + mTv_groupSelect.setText("公开群"); + tvInGroupDesc.setText("用户可主动申请入群,需群主审核"); + genderDialog.dismiss(); + break; + case R.id.rl_secrecy: + genderDialog.dismiss(); + break; + + } + }; + man.setOnClickListener(listener); + woman.setOnClickListener(listener); + secrecy.setOnClickListener(listener); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + String inputString = mEt_groupName.getText().toString(); + if (TextUtils.isEmpty(inputString)) { + mBtn_createGroup.setEnabled(false); + mBtn_createGroup.setClickable(false); + mBtn_createGroup.setBackgroundColor(Color.parseColor("#81E3E2")); + } else { + mBtn_createGroup.setClickable(true); + mBtn_createGroup.setEnabled(true); + mBtn_createGroup.setBackgroundColor(Color.parseColor("#2DD0CF")); + } + + } + + @Override + public void afterTextChanged(Editable s) { + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/SetGroupSilenceActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SetGroupSilenceActivity.java new file mode 100644 index 00000000..658847bf --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SetGroupSilenceActivity.java @@ -0,0 +1,65 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.os.Bundle; +import android.widget.Switch; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.utils.DialogCreator; +import jiguang.chat.utils.ToastUtil; + +/** + * Created by ${chenyn} on 2017/11/27. + */ + +public class SetGroupSilenceActivity extends BaseActivity { + private GroupInfo mGroupInfo; + private String mUserName; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_set_group_silence); + initTitle(true, true, "设置", "", false, ""); + + Switch switchButton = (Switch) findViewById(R.id.switchButton); + Dialog loadingDialog = DialogCreator.createLoadingDialog(SetGroupSilenceActivity.this, "正在加载..."); + loadingDialog.show(); + + long groupID = getIntent().getLongExtra("groupID", 0); + mUserName = getIntent().getStringExtra("userName"); + + JMessageClient.getGroupInfo(groupID, new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + if (i == 0) { + mGroupInfo = groupInfo; + switchButton.setChecked(groupInfo.isKeepSilence(mUserName, JMessageClient.getMyInfo().getAppKey())); + } + loadingDialog.dismiss(); + } + }); + + switchButton.setOnCheckedChangeListener((buttonView, isChecked) -> { + //如果是手动设置才走下面. + if (switchButton.isPressed()) { + mGroupInfo.setGroupMemSilence(mUserName, JMessageClient.getMyInfo().getAppKey(), isChecked, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + ToastUtil.shortToast(SetGroupSilenceActivity.this, "设置成功"); + } else { + ToastUtil.shortToast(SetGroupSilenceActivity.this, "设置失败" + i + s); + } + } + }); + } + }); + + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/SilenceUsersActivity.java b/chatapp/src/main/java/jiguang/chat/activity/SilenceUsersActivity.java new file mode 100644 index 00000000..512404f1 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/SilenceUsersActivity.java @@ -0,0 +1,168 @@ +package jiguang.chat.activity; + +import android.app.Dialog; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.File; +import java.util.List; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import cn.jpush.im.android.api.model.UserInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.utils.DialogCreator; + +/** + * Created by ${chenyn} on 2017/11/28. + */ + +public class SilenceUsersActivity extends BaseActivity { + + private ListView mLv_silenceUsers; + private List mSilenceMembers; + private String mGroupOwner; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_silence_users); + + initView(); + initData(); + } + + private void initView() { + initTitle(true, true, "群禁言列表", "", false, ""); + mLv_silenceUsers = (ListView) findViewById(R.id.lv_silenceUsers); + } + + private void initData() { + long groupID = getIntent().getLongExtra("groupID", 0); + Dialog loadingDialog = DialogCreator.createLoadingDialog(SilenceUsersActivity.this, "正在加载..."); + loadingDialog.show(); + JMessageClient.getGroupInfo(groupID, new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + loadingDialog.dismiss(); + if (i == 0) { + mGroupOwner = groupInfo.getGroupOwner(); + mSilenceMembers = groupInfo.getGroupSilenceMembers(); + mLv_silenceUsers.setAdapter(new SilenceMembersAdapter(groupInfo)); + } else { + Toast.makeText(SilenceUsersActivity.this, "没有禁言列表", Toast.LENGTH_SHORT).show(); + } + } + }); + + mLv_silenceUsers.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + UserInfo userInfo = (UserInfo) parent.getItemAtPosition(position); + Intent intent = new Intent(SilenceUsersActivity.this, GroupUserInfoActivity.class); + intent.putExtra("groupID", groupID); + intent.putExtra("groupUserName", userInfo.getUserName()); + intent.putExtra("groupOwner", mGroupOwner); + startActivity(intent); + } + }); + } + + class SilenceMembersAdapter extends BaseAdapter { + private GroupInfo mGroupInfo; + + public SilenceMembersAdapter(GroupInfo groupInfo) { + this.mGroupInfo = groupInfo; + } + + @Override + public int getCount() { + return mSilenceMembers == null ? 0 : mSilenceMembers.size(); + } + + @Override + public Object getItem(int position) { + return mSilenceMembers.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + UserInfo userInfo = mSilenceMembers.get(position); + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = View.inflate(SilenceUsersActivity.this, R.layout.item_silence_member, null); + holder.iv_userAvatar = convertView.findViewById(R.id.iv_userAvatar); + holder.tv_userName = convertView.findViewById(R.id.tv_userName); + holder.tv_delSilence = convertView.findViewById(R.id.tv_delSilence); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + String groupOwner = mGroupInfo.getGroupOwner(); + if (groupOwner.equals(JMessageClient.getMyInfo().getUserName())) { + holder.tv_delSilence.setVisibility(View.VISIBLE); + } else { + holder.tv_delSilence.setVisibility(View.GONE); + } + + File avatarFile = userInfo.getAvatarFile(); + if (avatarFile == null) { + userInfo.getBigAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + holder.iv_userAvatar.setImageBitmap(bitmap); + } else { + holder.iv_userAvatar.setImageResource(R.drawable.jmui_head_icon); + } + } + }); + } else { + holder.iv_userAvatar.setImageBitmap(BitmapFactory.decodeFile(avatarFile.getPath())); + } + + holder.tv_userName.setText(userInfo.getDisplayName()); + holder.tv_delSilence.setOnClickListener(v -> mGroupInfo.setGroupMemSilence(userInfo.getUserName(), userInfo.getAppKey(), false, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + Toast.makeText(SilenceUsersActivity.this, "取消成功", Toast.LENGTH_SHORT).show(); + mSilenceMembers.remove(userInfo); + } else { + Toast.makeText(SilenceUsersActivity.this, "取消失败", Toast.LENGTH_SHORT).show(); + } + notifyDataSetChanged(); + } + })); + + return convertView; + } + + class ViewHolder { + ImageView iv_userAvatar; + TextView tv_userName; + TextView tv_delSilence; + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/VerificationActivity.java b/chatapp/src/main/java/jiguang/chat/activity/VerificationActivity.java index 608b5c23..32a649ab 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/VerificationActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/VerificationActivity.java @@ -3,11 +3,8 @@ import android.app.Dialog; import android.os.Bundle; import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import android.widget.TextView; import cn.jpush.im.android.api.ContactManager; import cn.jpush.im.android.api.JMessageClient; @@ -42,22 +39,14 @@ protected void onCreate(Bundle savedInstanceState) { } private void initData() { - mEt_reason.setOnEditorActionListener(new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_SEND) { - sendAddReason(); - } - return false; - } - }); - - mJmui_commit_btn.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { + mEt_reason.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_SEND) { sendAddReason(); } + return false; }); + + mJmui_commit_btn.setOnClickListener(v -> sendAddReason()); } private void sendAddReason() { diff --git a/chatapp/src/main/java/jiguang/chat/activity/VerificationGroupActivity.java b/chatapp/src/main/java/jiguang/chat/activity/VerificationGroupActivity.java new file mode 100644 index 00000000..9b22fe74 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/VerificationGroupActivity.java @@ -0,0 +1,54 @@ +package jiguang.chat.activity; + +import android.os.Bundle; +import android.text.TextUtils; +import android.widget.EditText; +import android.widget.Toast; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.utils.HandleResponseCode; + +/** + * Created by ${chenyn} on 2017/11/6. + */ + +public class VerificationGroupActivity extends BaseActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_verification); + initTitle(true, true, "验证信息", "", true, "发送"); + EditText et_reason = (EditText) findViewById(R.id.et_reason); + et_reason.setHint("请填写验证信息"); + + mJmui_commit_btn.setOnClickListener(v -> { + //发送加入群组验证信息 + String verification = ""; + if (!TextUtils.isEmpty(et_reason.getText())) { + verification = et_reason.getText().toString(); + } + + long openGroupID = getIntent().getLongExtra("openGroupID", 0); + + JMessageClient.applyJoinGroup(openGroupID, verification, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + Toast.makeText(VerificationGroupActivity.this, "申请已发出,等待审核", Toast.LENGTH_SHORT).show(); + finish(); + } else { + HandleResponseCode.onHandle(VerificationGroupActivity.this, i, false); + } + } + }); + + + }); + + + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/VerificationMessageActivity.java b/chatapp/src/main/java/jiguang/chat/activity/VerificationMessageActivity.java new file mode 100644 index 00000000..c3d4d8e9 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/VerificationMessageActivity.java @@ -0,0 +1,66 @@ +package jiguang.chat.activity; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.widget.ImageButton; +import android.widget.RadioGroup; + +import java.util.ArrayList; +import java.util.List; + +import jiguang.chat.R; +import jiguang.chat.activity.fragment.FriendFragment; +import jiguang.chat.activity.fragment.GroupFragment; +import jiguang.chat.adapter.ViewPagerAdapter; +import jiguang.chat.view.NoScrollViewPager; + +/** + * Created by ${chenyn} on 2017/11/7. + */ + +public class VerificationMessageActivity extends FragmentActivity { + + private NoScrollViewPager mPager; + private List mFragmentList; + private RadioGroup mRg; + private int mCurTabIndex; + private ImageButton mReturn_btn; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_verification_message); + initData(); + } + + private void initData() { + mPager = findViewById(R.id.verification_viewpager); + mRg = findViewById(R.id.rg_verification); + mReturn_btn = findViewById(R.id.return_btn); + + mFragmentList = new ArrayList<>(); + mFragmentList.add(new FriendFragment()); + mFragmentList.add(new GroupFragment()); + mRg.check(R.id.rb_friend); + + mPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager(), mFragmentList)); + + mRg.setOnCheckedChangeListener((group, checkedId) -> { + switch (checkedId) { + case R.id.rb_friend: + mCurTabIndex = 0; + break; + case R.id.rb_group: + mCurTabIndex = 1; + break; + default: + break; + } + mPager.setCurrentItem(mCurTabIndex, false); + }); + + mReturn_btn.setOnClickListener(v -> finish()); + } + +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/fragment/BaseFragment.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/BaseFragment.java index 476192f2..39baf066 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/fragment/BaseFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/BaseFragment.java @@ -39,6 +39,7 @@ public class BaseFragment extends Fragment { protected int mAvatarSize; private Context mContext; public Activity mActivity; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/chatapp/src/main/java/jiguang/chat/activity/fragment/ChatRoomFragment.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/ChatRoomFragment.java new file mode 100644 index 00000000..ecdcdcbd --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/ChatRoomFragment.java @@ -0,0 +1,49 @@ +package jiguang.chat.activity.fragment; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import jiguang.chat.R; +import jiguang.chat.controller.ChatRoomController; +import jiguang.chat.view.ChatRoomView; + +/** + * Created by ${chenyn} on 2017/10/31. + */ + +public class ChatRoomFragment extends BaseFragment { + private Context mContext; + private View mRootView; + private ChatRoomView mChatRoomView; + private ChatRoomController mRoomController; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = this.getActivity(); + LayoutInflater layoutInflater = getActivity().getLayoutInflater(); + mRootView = layoutInflater.inflate(R.layout.fragment_chat_room, + getActivity().findViewById(R.id.main_view), false); + + mChatRoomView = mRootView.findViewById(R.id.chat_room_view); + mChatRoomView.initModule(); + mRoomController = new ChatRoomController(mChatRoomView, mContext); + + mChatRoomView.setListener(mRoomController); + mChatRoomView.setClickListener(mRoomController); + mChatRoomView.setOnRefreshListener(mRoomController); + mChatRoomView.setOnLoadMoreListener(mRoomController); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ViewGroup p = (ViewGroup) mRootView.getParent(); + if (p != null) { + p.removeAllViewsInLayout(); + } + return mRootView; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/fragment/ContactsFragment.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/ContactsFragment.java index 9d1246ee..1760dab0 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/fragment/ContactsFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/ContactsFragment.java @@ -6,6 +6,11 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; + +import com.google.gson.Gson; + +import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; import java.util.List; @@ -17,19 +22,23 @@ import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.callback.GetUserInfoListCallback; import cn.jpush.im.android.api.event.ContactNotifyEvent; +import cn.jpush.im.android.api.event.GroupApprovalEvent; +import cn.jpush.im.android.api.event.GroupApprovalRefuseEvent; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import jiguang.chat.R; import jiguang.chat.application.JGApplication; import jiguang.chat.controller.ContactsController; import jiguang.chat.database.FriendEntry; import jiguang.chat.database.FriendRecommendEntry; +import jiguang.chat.database.GroupApplyEntry; +import jiguang.chat.database.RefuseGroupEntry; import jiguang.chat.database.UserEntry; import jiguang.chat.entity.Event; import jiguang.chat.entity.EventType; import jiguang.chat.entity.FriendInvitation; +import jiguang.chat.entity.GroupApplyInvitation; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ThreadUtil; import jiguang.chat.utils.pinyin.HanziToPinyin; @@ -42,10 +51,10 @@ public class ContactsFragment extends BaseFragment { private View mRootView; private ContactsView mContactsView; + private TextView mAllContactNumber; private ContactsController mContactsController; private Activity mContext; - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -56,6 +65,7 @@ public void onCreate(Bundle savedInstanceState) { (ViewGroup) getActivity().findViewById(R.id.main_view), false); mContactsView = (ContactsView) mRootView.findViewById(R.id.contacts_view); + mAllContactNumber = getActivity().findViewById(R.id.all_contact_number); mContactsView.initModule(mRatio, mDensity); mContactsController = new ContactsController(mContactsView, this.getActivity()); @@ -210,6 +220,8 @@ public void gotResult(int status, String desc, UserInfo userInfo) { //收到好友请求数字 +1 int showNum = SharePreferenceManager.getCachedNewFriendNum() + 1; mContactsView.showNewFriends(showNum); + mAllContactNumber.setVisibility(View.VISIBLE); + mAllContactNumber.setText(String.valueOf(showNum)); SharePreferenceManager.setCachedNewFriendNum(showNum); } } @@ -239,6 +251,109 @@ public void onEventMainThread(Event event) { } } + //群主收到群组验证事件 + public void onEvent(GroupApprovalEvent event) { + final UserEntry user = JGApplication.getUserEntry(); + GroupApprovalEvent.Type type = event.getType(); + long gid = event.getGid(); + event.getFromUserInfo(new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo fromUserInfo) { + if (i == 0) { + Gson gson = new Gson(); + event.getApprovalUserInfoList(new GetUserInfoListCallback() { + @Override + public void gotResult(int i, String s, List list) { + if (i == 0) { + if (JGApplication.forAddIntoGroup.size() > 0) { + for (String addName : JGApplication.forAddIntoGroup) { + if (addName.equals(list.get(0).getUserName())) { + return; + } else { + JGApplication.forAddIntoGroup.add(list.get(0).getUserName()); + } + } + } + GroupApplyEntry entry; + //邀请,from是邀请方 + if (type.equals(GroupApprovalEvent.Type.invited_into_group)) { + entry = GroupApplyEntry.getEntry(user, list.get(0).getUserName(), list.get(0).getAppKey()); + if (entry != null) { + entry.delete(); + } + if (fromUserInfo.getAvatar() != null) { + entry = new GroupApplyEntry(fromUserInfo.getUserName(), list.get(0).getUserName(), fromUserInfo.getAppKey(), + list.get(0).getAvatarFile().getPath(), fromUserInfo.getDisplayName(), list.get(0).getDisplayName(), + null, GroupApplyInvitation.INVITED.getValue(), gson.toJson(event), gid + "", + user, 0, 0);//邀请type=0 + } else { + entry = new GroupApplyEntry(fromUserInfo.getUserName(), list.get(0).getUserName(), fromUserInfo.getAppKey(), + null, fromUserInfo.getDisplayName(), list.get(0).getDisplayName(), + null, GroupApplyInvitation.INVITED.getValue(), gson.toJson(event), gid + "", + user, 0, 0);//邀请type=0 + } + } else { + entry = GroupApplyEntry.getEntry(user, fromUserInfo.getUserName(), fromUserInfo.getAppKey()); + if (entry != null) { + entry.delete(); + } + if (fromUserInfo.getAvatar() != null) { + entry = new GroupApplyEntry(list.get(0).getUserName(), list.get(0).getUserName(), list.get(0).getAppKey(), + list.get(0).getAvatarFile().getPath(), list.get(0).getDisplayName(), list.get(0).getDisplayName(), + event.getReason(), GroupApplyInvitation.INVITED.getValue(), gson.toJson(event), gid + "", + user, 0, 1);//申请type=1 + } else { + entry = new GroupApplyEntry(list.get(0).getUserName(), list.get(0).getUserName(), list.get(0).getAppKey(), + null, fromUserInfo.getDisplayName(), list.get(0).getDisplayName(), + event.getReason(), GroupApplyInvitation.INVITED.getValue(), gson.toJson(event), gid + "", + user, 0, 1);//申请type=1 + } + } + entry.save(); + + int showNum = SharePreferenceManager.getCachedNewFriendNum() + 1; + mContactsView.showNewFriends(showNum); + mAllContactNumber.setVisibility(View.VISIBLE); + mAllContactNumber.setText(String.valueOf(showNum)); + + SharePreferenceManager.setCachedNewFriendNum(showNum); + } + } + }); + + } + } + }); + } + + //收到被拒绝事件 + public void onEvent(GroupApprovalRefuseEvent event) { + final UserEntry user = JGApplication.getUserEntry(); + long gid = event.getGid(); + event.getToUserInfoList(new GetUserInfoListCallback() { + @Override + public void gotResult(int i, String s, List list) { + if (i == 0) { + String userName = list.get(0).getUserName(); + String displayName = list.get(0).getDisplayName(); + String appKey = list.get(0).getAppKey(); + String path = null; + if (list.get(0).getAvatar() != null) { + path = list.get(0).getAvatarFile().getPath(); + } + RefuseGroupEntry groupEntry = RefuseGroupEntry.getEntry(user, userName, appKey); + if (groupEntry != null) { + groupEntry.delete(); + } + groupEntry = new RefuseGroupEntry(user, userName, displayName, gid + "", appKey, path); + groupEntry.save(); + + } + } + }); + + } + private String getLetter(String name) { String letter; ArrayList tokens = HanziToPinyin.getInstance() diff --git a/chatapp/src/main/java/jiguang/chat/activity/fragment/ConversationListFragment.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/ConversationListFragment.java index c6abc91a..18d3ed51 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/fragment/ConversationListFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/ConversationListFragment.java @@ -20,6 +20,10 @@ import android.view.WindowManager; import android.widget.PopupWindow; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; import cn.jpush.im.android.api.enums.ConversationType; @@ -32,7 +36,6 @@ import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import jiguang.chat.R; import jiguang.chat.application.JGApplication; import jiguang.chat.controller.ConversationListController; @@ -67,6 +70,9 @@ public class ConversationListFragment extends BaseFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (!EventBus.getDefault().isRegistered(this)) { + EventBus.getDefault().register(this); + } isCreate = true; mContext = this.getActivity(); @@ -199,7 +205,7 @@ public void gotResult(int responseCode, String responseMessage, Bitmap avatarBit */ public void onEvent(OfflineMessageEvent event) { Conversation conv = event.getConversation(); - if (!conv.getTargetId().equals("feedback_Android")) { + if (!conv.getTargetId().equals("feedback_Android") && conv.getType() != ConversationType.chatroom) { mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(REFRESH_CONVERSATION_LIST, conv)); } } @@ -226,7 +232,7 @@ public void onEventMainThread(MessageReceiptStatusChangeEvent event) { */ public void onEvent(ConversationRefreshEvent event) { Conversation conv = event.getConversation(); - if (!conv.getTargetId().equals("feedback_Android")) { + if (!conv.getTargetId().equals("feedback_Android") && conv.getType() != ConversationType.chatroom) { mBackgroundHandler.sendMessage(mBackgroundHandler.obtainMessage(REFRESH_CONVERSATION_LIST, conv)); //多端在线未读数改变时刷新 if (event.getReason().equals(ConversationRefreshEvent.Reason.UNREAD_CNT_UPDATED)) { @@ -246,7 +252,9 @@ public void handleMessage(android.os.Message msg) { switch (msg.what) { case REFRESH_CONVERSATION_LIST: Conversation conv = (Conversation) msg.obj; - mConvListController.getAdapter().setToTop(conv); + if (conv.getType() != ConversationType.chatroom) { + mConvListController.getAdapter().setToTop(conv); + } break; case DISMISS_REFRESH_HEADER: mContext.runOnUiThread(new Runnable() { @@ -264,7 +272,8 @@ public void run() { } } - public void onEventMainThread(Event event) { + @Subscribe(threadMode = ThreadMode.MAIN) + public void onEvent(Event event) { ; switch (event.getType()) { case createConversation: Conversation conv = event.getConversation(); @@ -311,6 +320,9 @@ public void onResume() { super.onResume(); dismissPopWindow(); mMenuItemView.showAddFriend(); + if (JGApplication.delConversation != null) { + mConvListController.delConversation(); + } mConvListController.getAdapter().notifyDataSetChanged(); } @@ -334,5 +346,4 @@ public void sortConvList() { mConvListController.getAdapter().sortConvList(); } } - } diff --git a/chatapp/src/main/java/jiguang/chat/activity/FriendRecommendActivity.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/FriendFragment.java similarity index 62% rename from chatapp/src/main/java/jiguang/chat/activity/FriendRecommendActivity.java rename to chatapp/src/main/java/jiguang/chat/activity/fragment/FriendFragment.java index 2d256082..8251d2ef 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/FriendRecommendActivity.java +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/FriendFragment.java @@ -1,8 +1,13 @@ -package jiguang.chat.activity; +package jiguang.chat.activity.fragment; +import android.app.Activity; import android.content.Intent; import android.os.Bundle; +import android.support.annotation.Nullable; import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import android.widget.ListView; import java.util.List; @@ -15,24 +20,23 @@ import jiguang.chat.entity.FriendInvitation; /** - * Created by ${chenyn} on 2017/3/17. - * - * 通讯录界面.验证消息 + * Created by ${chenyn} on 2017/11/7. */ -public class FriendRecommendActivity extends BaseActivity { +public class FriendFragment extends BaseFragment { + private Activity mContext; private ListView mListView; private FriendRecommendAdapter mAdapter; private List mList; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_friend_recommend); - - initView(); + this.mContext = getActivity(); + } + private void initData() { UserEntry user = JGApplication.getUserEntry(); if (null != user) { mList = user.getRecommends(); @@ -43,14 +47,21 @@ protected void onCreate(Bundle savedInstanceState) { } } - private void initView() { - initTitle(true, true, "新的朋友", "", false, ""); - mListView = (ListView) findViewById(R.id.friend_recommend_list_view); + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return initView(); + } + private View initView() { + View view = View.inflate(mContext, R.layout.verification_friend, null); + mListView = view.findViewById(R.id.friend_recommend_list_view); + initData(); + return view; } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (resultCode) { case JGApplication.RESULT_BUTTON: @@ -60,7 +71,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (btnState == 2) { entry.state = FriendInvitation.ACCEPTED.getValue(); entry.save(); - }else if (btnState == 1) { + } else if (btnState == 1) { entry.state = FriendInvitation.REFUSED.getValue(); entry.save(); } @@ -70,7 +81,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } } - protected void onResume() { + + @Override + public void onResume() { super.onResume(); mAdapter.notifyDataSetChanged(); } diff --git a/chatapp/src/main/java/jiguang/chat/activity/fragment/GroupFragment.java b/chatapp/src/main/java/jiguang/chat/activity/fragment/GroupFragment.java new file mode 100644 index 00000000..17c82331 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/activity/fragment/GroupFragment.java @@ -0,0 +1,175 @@ +package jiguang.chat.activity.fragment; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.List; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import jiguang.chat.R; +import jiguang.chat.activity.ApplyGroupInfoActivity; +import jiguang.chat.activity.GroupInfoActivity; +import jiguang.chat.adapter.GroupVerificationAdapter; +import jiguang.chat.application.JGApplication; +import jiguang.chat.database.GroupApplyEntry; +import jiguang.chat.database.RefuseGroupEntry; +import jiguang.chat.database.UserEntry; + +/** + * Created by ${chenyn} on 2017/11/7. + */ + +public class GroupFragment extends BaseFragment { + private Activity mContext; + private ListView mListView; + private List mRecommends; + private GroupVerificationAdapter mAdapter; + private List mRefuseGroupEntryList; + private LayoutInflater mInflater; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.mContext = getActivity(); + } + + private void initData() { + UserEntry user = JGApplication.getUserEntry(); + if (user != null) { + mRecommends = user.getGroupApplyRecommends(); + mAdapter = new GroupVerificationAdapter(mContext, mRecommends); + mListView.setAdapter(mAdapter); + + mRefuseGroupEntryList = user.getRefuseGroupRecommends(); + if (mRefuseGroupEntryList != null && mRefuseGroupEntryList.size() > 0) { + mListView.setAdapter(new RefuseGroupAdapter()); + } + } + + //点击事件要分类型 + mListView.setOnItemClickListener((parent, view, position, id) -> { + Intent intent = new Intent(); + Object itemAtPosition = parent.getItemAtPosition(position); + if (itemAtPosition instanceof GroupApplyEntry) { + intent.setClass(mContext, ApplyGroupInfoActivity.class); + GroupApplyEntry entry = (GroupApplyEntry) itemAtPosition; + intent.putExtra("toName", entry.toUsername); + intent.putExtra("reason", entry.reason); + startActivity(intent); + }else { + intent.setClass(mContext, GroupInfoActivity.class); + RefuseGroupEntry entry = (RefuseGroupEntry) itemAtPosition; + intent.setFlags(1); + intent.putExtra("groupId", entry.groupId); + startActivity(intent); + } + }); + + mListView.setOnItemLongClickListener((parent, view, position, id) -> { + + AlertDialog.Builder builder = new AlertDialog.Builder(mContext); + builder.setTitle("是否删除?").setPositiveButton("确定", (dialog, which) -> { + + GroupApplyEntry entry = (GroupApplyEntry) parent.getItemAtPosition(position); + entry.delete(); + mRecommends.remove(entry); + mAdapter.notifyDataSetChanged(); + + }).setNegativeButton("取消", (dialog, which) -> { + }).show(); + + return true; + }); + } + + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mInflater = LayoutInflater.from(mContext); + return initView(); + } + + private View initView() { + View view = View.inflate(mContext, R.layout.verification_group, null); + mListView = view.findViewById(R.id.group_recommend_list_view); + initData(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + mAdapter.notifyDataSetChanged(); + } + + class RefuseGroupAdapter extends BaseAdapter { + + @Override + public int getCount() { + return mRefuseGroupEntryList.size(); + } + + @Override + public Object getItem(int position) { + return mRefuseGroupEntryList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + RefuseGroupEntry entry = mRefuseGroupEntryList.get(position); + + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.item_refuse_group, null); + holder.groupAvatar = convertView.findViewById(R.id.groupAvatar); + holder.groupName = convertView.findViewById(R.id.groupName); + holder.refuseJoin = convertView.findViewById(R.id.refuseJoin); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + holder.refuseJoin.setText("群主拒绝 " + entry.displayName + " 入群"); + JMessageClient.getGroupInfo(Long.parseLong(entry.groupId), new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + if (i == 0) { + holder.groupName.setText(groupInfo.getGroupName()); + if (groupInfo.getAvatar() != null) { + holder.groupAvatar.setImageBitmap(BitmapFactory.decodeFile(groupInfo.getAvatarFile().getPath())); + } else { + holder.groupAvatar.setImageResource(R.drawable.group); + } + } + } + }); + return convertView; + } + + class ViewHolder { + ImageView groupAvatar; + TextView groupName; + TextView refuseJoin; + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/AudioFileAdapter.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/AudioFileAdapter.java index 0903b09c..68b94a76 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/AudioFileAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/AudioFileAdapter.java @@ -21,13 +21,13 @@ import cn.jpush.im.android.api.content.FileContent; import jiguang.chat.R; import jiguang.chat.activity.DownLoadActivity; -import jiguang.chat.adapter.StickyListHeadersAdapter; import jiguang.chat.entity.FileItem; import jiguang.chat.entity.SelectedHistoryFileListener; import jiguang.chat.utils.FileHelper; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ViewHolder; import jiguang.chat.view.MyImageView; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/8/29. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/DocumentFileAdapter.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/DocumentFileAdapter.java index 3fd881c2..f0e33053 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/DocumentFileAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/DocumentFileAdapter.java @@ -21,12 +21,12 @@ import cn.jpush.im.android.api.content.FileContent; import jiguang.chat.R; import jiguang.chat.activity.DownLoadActivity; -import jiguang.chat.adapter.StickyListHeadersAdapter; import jiguang.chat.entity.FileItem; import jiguang.chat.entity.SelectedHistoryFileListener; import jiguang.chat.utils.FileHelper; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ViewHolder; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/8/29. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/OtherFileAdapter.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/OtherFileAdapter.java index 73847c6d..341a714d 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/OtherFileAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/OtherFileAdapter.java @@ -21,13 +21,13 @@ import cn.jpush.im.android.api.content.FileContent; import jiguang.chat.R; import jiguang.chat.activity.DownLoadActivity; -import jiguang.chat.adapter.StickyListHeadersAdapter; import jiguang.chat.entity.FileItem; import jiguang.chat.entity.SelectedHistoryFileListener; import jiguang.chat.utils.FileHelper; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ViewHolder; import jiguang.chat.view.MyImageView; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/8/29. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/VideoFileAdapter.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/VideoFileAdapter.java index 5effb3ea..521deecf 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/VideoFileAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/adapter/VideoFileAdapter.java @@ -21,13 +21,13 @@ import cn.jpush.im.android.api.content.FileContent; import jiguang.chat.R; import jiguang.chat.activity.DownLoadActivity; -import jiguang.chat.adapter.StickyListHeadersAdapter; import jiguang.chat.entity.FileItem; import jiguang.chat.entity.SelectedHistoryFileListener; import jiguang.chat.utils.FileHelper; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ViewHolder; import jiguang.chat.view.MyImageView; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/8/29. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/AudioFileFragment.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/AudioFileFragment.java index 62934329..b74de258 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/AudioFileFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/AudioFileFragment.java @@ -26,7 +26,7 @@ import jiguang.chat.activity.historyfile.adapter.AudioFileAdapter; import jiguang.chat.activity.historyfile.controller.HistoryFileController; import jiguang.chat.entity.FileItem; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** * Created by ${chenyn} on 2017/8/23. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/DocumentFileFragment.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/DocumentFileFragment.java index 399c474a..c8ee6dc3 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/DocumentFileFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/DocumentFileFragment.java @@ -26,7 +26,7 @@ import jiguang.chat.activity.historyfile.adapter.DocumentFileAdapter; import jiguang.chat.activity.historyfile.controller.HistoryFileController; import jiguang.chat.entity.FileItem; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** * Created by ${chenyn} on 2017/8/23. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/OtherFileFragment.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/OtherFileFragment.java index db5308de..461d71ad 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/OtherFileFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/OtherFileFragment.java @@ -26,7 +26,7 @@ import jiguang.chat.activity.historyfile.adapter.OtherFileAdapter; import jiguang.chat.activity.historyfile.controller.HistoryFileController; import jiguang.chat.entity.FileItem; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** * Created by ${chenyn} on 2017/8/23. diff --git a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/VideoFileFragment.java b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/VideoFileFragment.java index b76d91f9..55506b0d 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/VideoFileFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/historyfile/fragment/VideoFileFragment.java @@ -26,7 +26,7 @@ import jiguang.chat.activity.historyfile.adapter.VideoFileAdapter; import jiguang.chat.activity.historyfile.controller.HistoryFileController; import jiguang.chat.entity.FileItem; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** * Created by ${chenyn} on 2017/8/23. diff --git a/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageAlreadyReadFragment.java b/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageAlreadyReadFragment.java index cf391130..1b4e48cc 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageAlreadyReadFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageAlreadyReadFragment.java @@ -30,6 +30,7 @@ public class MessageAlreadyReadFragment extends BaseFragment { public MessageAlreadyReadFragment(long groupIdForReceipt) { this.mGroupId = groupIdForReceipt; } + public MessageAlreadyReadFragment() { } diff --git a/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageNotReadFragment.java b/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageNotReadFragment.java index 2d840403..1d0e418a 100644 --- a/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageNotReadFragment.java +++ b/chatapp/src/main/java/jiguang/chat/activity/receiptmessage/MessageNotReadFragment.java @@ -19,7 +19,6 @@ /** * Created by ${chenyn} on 2017/9/5. */ - public class MessageNotReadFragment extends BaseFragment{ private Activity mContext; private View mRootView; diff --git a/chatapp/src/main/java/jiguang/chat/adapter/AppsAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/AppsAdapter.java index 60aae137..262f4a1d 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/AppsAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/AppsAdapter.java @@ -8,9 +8,10 @@ import android.widget.ImageView; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; -import cn.jpush.im.android.eventbus.EventBus; import jiguang.chat.R; import jiguang.chat.application.JGApplication; import jiguang.chat.model.AppBean; diff --git a/chatapp/src/main/java/jiguang/chat/adapter/AtMemberAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/AtMemberAdapter.java index 55c5180e..4a3b064c 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/AtMemberAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/AtMemberAdapter.java @@ -19,6 +19,7 @@ import jiguang.chat.R; import jiguang.chat.utils.ViewHolder; import jiguang.chat.utils.pinyin.HanziToPinyin; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; public class AtMemberAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer { diff --git a/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomAdapter.java new file mode 100644 index 00000000..79ce5a8a --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomAdapter.java @@ -0,0 +1,76 @@ +package jiguang.chat.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.List; + +import cn.jpush.im.android.api.model.ChatRoomInfo; +import jiguang.chat.R; +import jiguang.chat.view.ChatRoomView; + +/** + * Created by ${chenyn} on 2017/10/31. + */ + +public class ChatRoomAdapter extends BaseAdapter { + private Context mContext; + private List mChatRoomInfoList; + private ChatRoomView mChatRoomView; + private LayoutInflater mInflater; + + public ChatRoomAdapter(Context context, List chatRoomData, ChatRoomView chatRoomView) { + this.mContext = context; + this.mChatRoomInfoList = chatRoomData; + this.mChatRoomView = chatRoomView; + this.mInflater = LayoutInflater.from(context); + } + + @Override + public int getCount() { + return mChatRoomInfoList == null ? 0 : mChatRoomInfoList.size(); + } + + @Override + public Object getItem(int i) { + return mChatRoomInfoList.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int position, View convertView, ViewGroup viewGroup) { + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.item_chat_room, null); + holder.iv_chatRoomAvatar = convertView.findViewById(R.id.iv_chatRoomAvatar); + holder.tv_chatRoomName = convertView.findViewById(R.id.tv_chatRoomName); + holder.tv_chatRoomContent = convertView.findViewById(R.id.tv_chatRoomContent); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + ChatRoomInfo chatRoomInfo = mChatRoomInfoList.get(position); + holder.tv_chatRoomName.setText(chatRoomInfo.getName()); + holder.tv_chatRoomContent.setText(chatRoomInfo.getDescription()); + + + return convertView; + } + + class ViewHolder { + ImageView iv_chatRoomAvatar; + TextView tv_chatRoomName; + TextView tv_chatRoomContent; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperGridAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperGridAdapter.java new file mode 100644 index 00000000..59257cb6 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperGridAdapter.java @@ -0,0 +1,60 @@ +package jiguang.chat.adapter; + +import android.content.Context; +import android.graphics.Bitmap; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; + +import java.util.List; + +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; + +public class ChatRoomKeeperGridAdapter extends BaseAdapter { + private Context context; + private List keeperList; + + public ChatRoomKeeperGridAdapter(Context context, List keeperList) { + this.context = context; + this.keeperList = keeperList; + } + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ImageView avatar; + if (convertView == null) { + convertView = LayoutInflater.from(context).inflate(R.layout.item_chatroom_avatar, null); + } + avatar = ((ImageView) convertView.findViewById(R.id.grid_avatar)); + UserInfo userInfo = keeperList.get(position); + if (userInfo != null) { + userInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + avatar.setImageBitmap(bitmap); + } + } + }); + } + return convertView; + } + + @Override + public Object getItem(int position) { + return keeperList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public int getCount() { + return keeperList != null ? keeperList.size() : 0; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperListAdapter.java new file mode 100644 index 00000000..d8b0618f --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/adapter/ChatRoomKeeperListAdapter.java @@ -0,0 +1,125 @@ +package jiguang.chat.adapter; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.Collections; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.model.UserInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.activity.ChatRoomKeeperActivity; +import jiguang.chat.activity.GroupUserInfoActivity; +import jiguang.chat.activity.PersonalActivity; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.DialogCreator; + +public class ChatRoomKeeperListAdapter extends BaseAdapter implements AdapterView.OnItemClickListener { + private List keepers; + private Context context; + private LayoutInflater mInflater; + private long roomId; + private boolean isOwner; + + public ChatRoomKeeperListAdapter(Context context, List keepers, long roomId, boolean isOwner) { + this.context = context; + this.keepers = keepers; + this.mInflater = LayoutInflater.from(context); + this.roomId = roomId; + this.isOwner = isOwner; + } + + @Override + public Object getItem(int position) { + return keepers.get(position); + } + + @Override + public int getCount() { + return keepers.size(); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.item_chat_room_keeper, null); + holder.iv_keeperAvatar = convertView.findViewById(R.id.icon_iv); + holder.tv_keeperName = convertView.findViewById(R.id.name); + holder.bt_remove = convertView.findViewById(R.id.bt_removeKeeper); + if (!isOwner) { + holder.bt_remove.setVisibility(View.GONE); + } else { + holder.bt_remove.setOnClickListener((v)-> { + Dialog dialog = DialogCreator.createLoadingDialog(context, "移出中"); + dialog.show(); + ChatRoomManager.delChatRoomAdmin(roomId, Collections.singletonList(keepers.get(position).data), new BasicCallback() { + @Override + public void gotResult(int i, String s) { + dialog.dismiss(); + if (i == 0) { + keepers.remove(position); + notifyDataSetChanged(); + } + } + }); + }); + } + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + holder.iv_keeperAvatar.setImageResource(R.drawable.rc_default_portrait); + UserInfo userInfo = keepers.get(position).data; + userInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + holder.iv_keeperAvatar.setImageBitmap(bitmap); + } + } + }); + holder.tv_keeperName.setText(keepers.get(position).highlight); + return convertView; + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Intent intent = new Intent(); + if (keepers.get(position).data.getUserID() == JMessageClient.getMyInfo().getUserID()) { + intent.setClass(context, PersonalActivity.class); + } else { + intent.setClass(context, GroupUserInfoActivity.class); + intent.putExtra(GroupUserInfoActivity.IS_FROM_GROUP, false); + intent.putExtra(JGApplication.NAME, keepers.get(position).data != null ? keepers.get(position).data.getUserName() : ""); + intent.putExtra(JGApplication.TARGET_APP_KEY, keepers.get(position).data != null ? keepers.get(position).data.getAppKey() : ""); + } + context.startActivity(intent); + } + + class ViewHolder { + ImageView iv_keeperAvatar; + TextView tv_keeperName; + Button bt_remove; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/adapter/ChattingListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/ChattingListAdapter.java index c0ef6c34..719b1c05 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/ChattingListAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/ChattingListAdapter.java @@ -96,6 +96,7 @@ public class ChattingListAdapter extends BaseAdapter { private ChatItemController mController; private Dialog mDialog; private boolean mHasLastPage = false; + private boolean isChatRoom = false; public ChattingListAdapter(Activity context, Conversation conv, ContentLongClickListener longClickListener) { this.mContext = context; @@ -123,10 +124,12 @@ public void gotResult(int status, String desc, Bitmap bitmap) { } }); } - } else { + } else if (mConv.getType() == ConversationType.group) { //群聊 GroupInfo groupInfo = (GroupInfo) mConv.getTargetInfo(); mGroupId = groupInfo.getGroupID(); + } else { + isChatRoom = true; } checkSendingImgMsg(); } @@ -169,6 +172,7 @@ public void dropDownToRefresh() { List msgList = mConv.getMessagesFromNewest(mMsgList.size(), PAGE_MESSAGE_COUNT); if (msgList != null) { for (Message msg : msgList) { + // TODO:2019/04/23 这里是否效率低下,每次都需要移动整个list mMsgList.add(0, msg); } if (msgList.size() > 0) { @@ -224,8 +228,7 @@ private void checkSendingImgMsg() { } } - public void setSendMsgs(int msgIds) { - Message msg = mConv.getMessage(msgIds); + public void setSendMsgs(Message msg) { if (msg != null) { mMsgList.add(msg); incrementStartPosition(); @@ -452,7 +455,7 @@ public void clearMsgList() { public View getView(final int position, View convertView, ViewGroup parent) { final Message msg = mMsgList.get(position); //消息接收方发送已读回执 - if (msg.getDirect() == MessageDirect.receive && !msg.haveRead()) { + if (msg.getDirect() == MessageDirect.receive && !msg.haveRead() && !isChatRoom) { msg.setHaveRead(new BasicCallback() { @Override public void gotResult(int i, String s) { @@ -509,9 +512,7 @@ public void gotResult(int i, String s) { holder.picture = (ImageView) convertView.findViewById(R.id.jmui_picture_iv); holder.locationView = convertView.findViewById(R.id.location_view); break; - case custom: - case prompt: - case eventNotification: + default: holder.groupChange = (TextView) convertView.findViewById(R.id.jmui_group_content); break; } @@ -646,10 +647,18 @@ public void onClick(View arg0) { case prompt: mController.handlePromptMsg(msg, holder); break; - default: + case custom: mController.handleCustomMsg(msg, holder); + break; + default: + mController.handleUnSupportMsg(msg, holder); + break; + } + if (isChatRoom && holder.text_receipt != null) { + holder.text_receipt.setVisibility(View.GONE); } - if (msg.getDirect() == MessageDirect.send && !msg.getContentType().equals(ContentType.prompt) && msg.getContentType() != ContentType.custom) { + if (msg.getDirect() == MessageDirect.send && !msg.getContentType().equals(ContentType.prompt) + && msg.getContentType() != ContentType.custom && !isChatRoom && msg.getContentType() != ContentType.video) { if (msg.getUnreceiptCnt() == 0) { if (msg.getTargetType() == ConversationType.group) { holder.text_receipt.setText("全部已读"); @@ -880,4 +889,10 @@ public boolean onLongClick(View v) { public abstract void onContentLongClick(int position, View view); } + public void stopMediaPlayer() { + if (mController != null) { + mController.stopMediaPlayer(); + } + } + } \ No newline at end of file diff --git a/chatapp/src/main/java/jiguang/chat/adapter/ConversationListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/ConversationListAdapter.java index 3961d0a3..3f363634 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/ConversationListAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/ConversationListAdapter.java @@ -33,6 +33,7 @@ import cn.jpush.im.android.api.enums.ContentType; import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.enums.MessageDirect; +import cn.jpush.im.android.api.enums.MessageStatus; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.Message; @@ -234,6 +235,7 @@ public View getView(final int position, View convertView, final ViewGroup parent ImageView groupBlocked = ViewHolder.get(convertView, R.id.iv_groupBlocked); ImageView newMsgDisturb = ViewHolder.get(convertView, R.id.new_group_msg_disturb); ImageView newGroupMsgDisturb = ViewHolder.get(convertView, R.id.new_msg_disturb); + ImageView convListSendFail = ViewHolder.get(convertView, R.id.iv_convListSendFail); final SwipeLayoutConv swipeLayout = ViewHolder.get(convertView, R.id.swp_layout); final TextView delete = ViewHolder.get(convertView, R.id.tv_delete); @@ -250,7 +252,7 @@ public View getView(final int position, View convertView, final ViewGroup parent Message lastMsg = convItem.getLatestMessage(); if (lastMsg != null) { TimeFormat timeFormat = new TimeFormat(mContext, lastMsg.getCreateTime()); -// //会话界面时间 + //会话界面时间 datetime.setText(timeFormat.getTime()); String contentStr; switch (lastMsg.getContentType()) { @@ -294,6 +296,12 @@ public View getView(final int position, View convertView, final ViewGroup parent break; } + if (lastMsg.getStatus() == MessageStatus.send_fail) { + convListSendFail.setVisibility(View.VISIBLE); + }else { + convListSendFail.setVisibility(View.GONE); + } + MessageContent msgContent = lastMsg.getContent(); Boolean isRead = msgContent.getBooleanExtra("isRead"); Boolean isReadAtAll = msgContent.getBooleanExtra("isReadAtAll"); @@ -358,7 +366,11 @@ public View getView(final int position, View convertView, final ViewGroup parent !lastMsg.getContentType().equals(ContentType.prompt) && //排除自己给自己发送消息 !((UserInfo) lastMsg.getTargetInfo()).getUserName().equals(JMessageClient.getMyInfo().getUserName())) { - content.setText("[已读]" + contentStr); + if (lastMsg.getStatus() == MessageStatus.send_fail) { + content.setText(contentStr); + }else { + content.setText("[已读]" + contentStr); + } } else { content.setText(contentStr); } @@ -416,7 +428,7 @@ public void gotResult(int status, String desc, Bitmap bitmap) { } else { headIcon.setImageResource(R.drawable.jmui_head_icon); } - } else { + } else if (convItem.getType().equals(ConversationType.group)) { mGroupInfo = (GroupInfo) convItem.getTargetInfo(); if (mGroupInfo != null) { mGroupInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { diff --git a/chatapp/src/main/java/jiguang/chat/adapter/FriendListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/FriendListAdapter.java index 4c6a4b05..e90448f1 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/FriendListAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/FriendListAdapter.java @@ -20,6 +20,7 @@ import cn.jpush.im.android.api.model.UserInfo; import jiguang.chat.R; import jiguang.chat.database.FriendEntry; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/9/21. diff --git a/chatapp/src/main/java/jiguang/chat/adapter/FriendRecommendAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/FriendRecommendAdapter.java index 954e9624..d8ecd766 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/FriendRecommendAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/FriendRecommendAdapter.java @@ -1,9 +1,10 @@ package jiguang.chat.adapter; -import android.app.Activity; import android.app.Dialog; +import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; +import android.support.v4.app.Fragment; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -12,6 +13,8 @@ import android.widget.LinearLayout; import android.widget.TextView; +import org.greenrobot.eventbus.EventBus; + import java.util.ArrayList; import java.util.List; @@ -20,7 +23,6 @@ import cn.jpush.im.android.api.callback.GetUserInfoCallback; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.activity.FriendInfoActivity; @@ -46,19 +48,21 @@ public class FriendRecommendAdapter extends BaseAdapter { - private Activity mContext; + private Fragment mFragment; + private Context mContext; private List mList = new ArrayList<>(); private LayoutInflater mInflater; private float mDensity; private int mWidth; - public FriendRecommendAdapter(Activity context, List list, float density, + public FriendRecommendAdapter(Fragment fragment, List list, float density, int width) { - this.mContext = context; - this.mList = list; - this.mInflater = LayoutInflater.from(mContext); - this.mDensity = density; - this.mWidth = width; + mFragment = fragment; + mContext = mFragment.getActivity(); + mList = list; + mInflater = LayoutInflater.from(mContext); + mDensity = density; + mWidth = width; } @Override @@ -201,7 +205,7 @@ public void onClick(View view) { intent.putExtra("position", position); intent.putExtra(JGApplication.TARGET_ID, entry.username); intent.putExtra(JGApplication.TARGET_APP_KEY, entry.appKey); - mContext.startActivityForResult(intent, 0); + mFragment.startActivityForResult(intent, 0); //2.已经添加的 --> 好友详情 } else if (entry.state.equals(FriendInvitation.ACCEPTED.getValue())) { JMessageClient.getUserInfo(item.username, new GetUserInfoCallback() { @@ -217,7 +221,7 @@ public void gotResult(int i, String s, UserInfo userInfo) { } intent1.putExtra(JGApplication.TARGET_ID, entry.username); intent1.putExtra(JGApplication.TARGET_APP_KEY, entry.appKey); - mContext.startActivityForResult(intent1, 0); + mFragment.startActivityForResult(intent1, 0); } } }); @@ -228,7 +232,7 @@ public void gotResult(int i, String s, UserInfo userInfo) { intent.putExtra("reason", item.reason); intent.putExtra(JGApplication.TARGET_ID, entry.username); intent.putExtra(JGApplication.TARGET_APP_KEY, entry.appKey); - mContext.startActivityForResult(intent, 0); + mFragment.startActivityForResult(intent, 0); } } @@ -297,7 +301,7 @@ public void onClick(View view) { } intent.putExtra(JGApplication.TARGET_ID, entry.username); intent.putExtra(JGApplication.TARGET_APP_KEY, entry.appKey); - mContext.startActivityForResult(intent, 0); + mFragment.startActivityForResult(intent, 0); } }); } diff --git a/chatapp/src/main/java/jiguang/chat/adapter/GroupListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/GroupListAdapter.java index 7e77b040..900ee4b7 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/GroupListAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/GroupListAdapter.java @@ -15,6 +15,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,7 +29,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.activity.ChatActivity; diff --git a/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberGridAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberGridAdapter.java index 0cfbd010..9d10cc54 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberGridAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberGridAdapter.java @@ -34,7 +34,7 @@ public class GroupMemberGridAdapter extends BaseAdapter { private int mCurrentNum; //用群成员项数余4得到,作为下标查找mRestArray,得到空白项 private int mRestNum; - private static final int MAX_GRID_ITEM = 40; + private int maxGridItem; private boolean mIsGroup; private String mTargetId; private Context mContext; @@ -53,6 +53,7 @@ public GroupMemberGridAdapter(Context context, List memberList, boolea this.mMemberList = memberList; mCurrentNum = mMemberList.size(); this.mIsCreator = isCreator; + maxGridItem = isCreator ? 13 : 14; this.mAvatarSize = size; initBlankItem(mCurrentNum); } @@ -66,8 +67,8 @@ public GroupMemberGridAdapter(Context context, String targetId, String appKey) { } public void initBlankItem(int size) { - if (mMemberList.size() > MAX_GRID_ITEM) { - mCurrentNum = MAX_GRID_ITEM - 1; + if (mMemberList.size() > maxGridItem) { + mCurrentNum = maxGridItem; } else { mCurrentNum = mMemberList.size(); } @@ -75,8 +76,8 @@ public void initBlankItem(int size) { } public void refreshMemberList() { - if (mMemberList.size() > MAX_GRID_ITEM) { - mCurrentNum = MAX_GRID_ITEM - 1; + if (mMemberList.size() > maxGridItem) { + mCurrentNum = maxGridItem; } else { mCurrentNum = mMemberList.size(); } diff --git a/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberListAdapter.java new file mode 100644 index 00000000..faeeba13 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/adapter/GroupMemberListAdapter.java @@ -0,0 +1,238 @@ +package jiguang.chat.adapter; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.SectionIndexer; +import android.widget.TextView; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.model.GroupInfo; +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.R; +import jiguang.chat.activity.GroupMemberListActivity; +import jiguang.chat.utils.pinyin.HanziToPinyin; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; + +/** + * Created by ${chenyn} on 2017/11/3. + */ + +public class GroupMemberListAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer { + + private List mMemberList; + private final LayoutInflater mInflater; + + private int[] mSectionIndices; + private String[] mSectionLetters; + private long mGroupID; + + public GroupMemberListAdapter(GroupMemberListActivity context, List memberInfoList, long groupId) { + mInflater = LayoutInflater.from(context); + this.mMemberList = memberInfoList; + this.mGroupID = groupId; + + //想要给listView增加分组,数据源要排序才行 + mSectionIndices = getSectionIndices(); + mSectionLetters = getSectionLetters(); + } + + @Override + public int getCount() { + return mMemberList == null ? 0 : mMemberList.size(); + } + + @Override + public Object getItem(int position) { + return mMemberList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewholder; + if (convertView == null) { + viewholder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.item_group_member_list, parent, false); + viewholder.iv_memberAvatar = convertView.findViewById(R.id.iv_memberAvatar); + viewholder.tv_memberName = convertView.findViewById(R.id.tv_memberName); + viewholder.iv_gag = convertView.findViewById(R.id.iv_silence); + convertView.setTag(viewholder); + } else { + viewholder = (ViewHolder) convertView.getTag(); + } + + UserInfo userInfo = mMemberList.get(position); + File file = userInfo.getAvatarFile(); + if (file != null) { + if (file.exists()) { + viewholder.iv_memberAvatar.setImageBitmap(BitmapFactory.decodeFile(userInfo.getAvatarFile().getPath())); + } else { + userInfo.getBigAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + viewholder.iv_memberAvatar.setImageBitmap(bitmap); + } + } + }); + } + } else { + viewholder.iv_memberAvatar.setImageResource(R.drawable.jmui_head_icon); + } + + viewholder.tv_memberName.setText(userInfo.getDisplayName()); + + JMessageClient.getGroupInfo(mGroupID, new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + if (i == 0) { + boolean keepSilence = groupInfo.isKeepSilence(userInfo.getUserName(), userInfo.getAppKey()); + if (keepSilence) { + viewholder.iv_gag.setVisibility(View.VISIBLE); + }else { + viewholder.iv_gag.setVisibility(View.GONE); + } + } + } + }); + + return convertView; + } + + @Override + public View getHeaderView(int position, View convertView, ViewGroup parent) { + convertView = mInflater.inflate(R.layout.header, parent, false); + TextView headView = convertView.findViewById(R.id.section_tv); + UserInfo userInfo = mMemberList.get(position); + + int forPosition = getSectionForPosition(position); + headView.setText(getLetter(userInfo.getDisplayName())); + if (position == getPositionForSection(forPosition)) { + headView.setText(getLetter(userInfo.getDisplayName())); + } + return convertView; + } + + @Override + public long getHeaderId(int position) { + String letter = getLetter(mMemberList.get(position).getDisplayName()); + return letter.charAt(0); + } + + class ViewHolder { + ImageView iv_memberAvatar; + TextView tv_memberName; + ImageView iv_gag; + } + + private int[] getSectionIndices() { + ArrayList sectionIndices = new ArrayList(); + if (mMemberList.size() > 0) { + char lastFirstChar = getLetter(mMemberList.get(0).getDisplayName()).charAt(0); + sectionIndices.add(0); + for (int i = 1; i < mMemberList.size(); i++) { + if (getLetter(mMemberList.get(i).getDisplayName()).charAt(0) != lastFirstChar) { + lastFirstChar = getLetter(mMemberList.get(i).getDisplayName()).charAt(0); + sectionIndices.add(i); + } + } + int[] sections = new int[sectionIndices.size()]; + for (int i = 0; i < sectionIndices.size(); i++) { + sections[i] = sectionIndices.get(i); + } + return sections; + } + return null; + } + + private String[] getSectionLetters() { + if (null != mSectionIndices) { + String[] letters = new String[mSectionIndices.length]; + for (int i = 0; i < mSectionIndices.length; i++) { + letters[i] = getLetter(mMemberList.get(mSectionIndices[i]).getDisplayName()); + } + return letters; + } + return null; + } + + @Override + public Object[] getSections() { + return mSectionLetters; + } + + @Override + public int getPositionForSection(int sectionIndex) { + if (mSectionIndices == null || mSectionIndices.length == 0) { + return 0; + } + if (sectionIndex >= mSectionIndices.length) { + sectionIndex = mSectionIndices.length - 1; + } else if (sectionIndex < 0) { + sectionIndex = 0; + } + return mSectionIndices[sectionIndex]; + } + + @Override + public int getSectionForPosition(int position) { + if (null != mSectionIndices) { + for (int i = 0; i < mSectionIndices.length; i++) { + if (position < mSectionIndices[i]) { + return i - 1; + } + } + return mSectionIndices.length - 1; + } + return -1; + } + + public int getSectionForLetter(String letter) { + if (null != mSectionIndices) { + for (int i = 0; i < mSectionIndices.length; i++) { + if (mSectionLetters[i].equals(letter)) { + return mSectionIndices[i] + 1; + } + } + } + return -1; + } + + public String getLetter(String name) { + String letter; + ArrayList tokens = HanziToPinyin.getInstance() + .get(name); + StringBuilder sb = new StringBuilder(); + if (tokens != null && tokens.size() > 0) { + for (HanziToPinyin.Token token : tokens) { + if (token.type == HanziToPinyin.Token.PINYIN) { + sb.append(token.target); + } else { + sb.append(token.source); + } + } + } + String sortString = sb.toString().substring(0, 1).toUpperCase(); + if (sortString.matches("[A-Z]")) { + letter = sortString.toUpperCase(); + } else { + letter = "#"; + } + return letter; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/adapter/GroupVerificationAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/GroupVerificationAdapter.java new file mode 100644 index 00000000..c5c8af08 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/adapter/GroupVerificationAdapter.java @@ -0,0 +1,222 @@ +package jiguang.chat.adapter; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; + +import java.io.File; +import java.util.List; + +import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.callback.GetAvatarBitmapCallback; +import cn.jpush.im.android.api.callback.GetGroupInfoCallback; +import cn.jpush.im.android.api.callback.GetUserInfoCallback; +import cn.jpush.im.android.api.event.GroupApprovalEvent; +import cn.jpush.im.android.api.model.GroupInfo; +import cn.jpush.im.android.api.model.UserInfo; +import cn.jpush.im.api.BasicCallback; +import jiguang.chat.R; +import jiguang.chat.database.GroupApplyEntry; + +/** + * Created by ${chenyn} on 2017/11/7. + */ + +public class GroupVerificationAdapter extends BaseAdapter { + private Activity mContext; + private final LayoutInflater mInflater; + private List recommends; + private File mFile; + + public GroupVerificationAdapter(Activity context, List recommends) { + this.mContext = context; + this.recommends = recommends; + mInflater = LayoutInflater.from(mContext); + } + + @Override + public int getCount() { + return recommends.size(); + } + + @Override + public Object getItem(int position) { + return recommends.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + GroupApplyEntry entry = recommends.get(position); + + ViewHolder holder; + if (convertView == null) { + holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.item_group_owner_recomend, null); + holder.iv_groupAvatar = convertView.findViewById(R.id.item_head_icon); + holder.item_name = convertView.findViewById(R.id.item_name); + holder.item_reason = convertView.findViewById(R.id.item_reason); + holder.tv_groupInvite = convertView.findViewById(R.id.tv_groupInvite); + holder.item_add_btn = convertView.findViewById(R.id.item_add_btn); + holder.item_state = convertView.findViewById(R.id.item_state); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + if (entry.Avatar != null) { + mFile = new File(entry.Avatar); + if (mFile.exists()) { + holder.iv_groupAvatar.setImageBitmap(BitmapFactory.decodeFile(entry.Avatar)); + } else { + JMessageClient.getUserInfo(entry.toUsername, new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + if (i == 0) { + userInfo.getAvatarBitmap(new GetAvatarBitmapCallback() { + @Override + public void gotResult(int i, String s, Bitmap bitmap) { + if (i == 0) { + holder.iv_groupAvatar.setImageBitmap(bitmap); + } else { + holder.iv_groupAvatar.setImageResource(R.drawable.jmui_head_icon); + } + } + }); + } + } + }); + } + } else { + holder.iv_groupAvatar.setImageResource(R.drawable.jmui_head_icon); + + } + + + JMessageClient.getGroupInfo(Long.parseLong(entry.groupName), new GetGroupInfoCallback() { + @Override + public void gotResult(int i, String s, GroupInfo groupInfo) { + holder.item_reason.setText("申请加入群 " + groupInfo.getGroupName()); + //邀请 + if (entry.groupType == 0) { + holder.item_name.setText(entry.toDisplayName); + holder.tv_groupInvite.setText("邀请人:" + entry.fromDisplayName);//事件发起人 + } else { + holder.item_name.setText(entry.toDisplayName); + holder.tv_groupInvite.setText(entry.reason); + } + } + }); + + //申请 + //0为初始状态 + Gson gson = new Gson(); + GroupApprovalEvent event = gson.fromJson(entry.eventJson, GroupApprovalEvent.class); + if (entry.btnState == 0) { + holder.item_add_btn.setBackgroundColor(Color.parseColor("#2DD0CF")); + holder.item_add_btn.setTextColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setText("同意"); + holder.item_add_btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //邀请 + event.acceptGroupApproval(entry.toUsername, entry.appKey, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + //同意加入群组 + Toast.makeText(mContext, "添加成功", Toast.LENGTH_SHORT).show(); + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已同意"); + entry.btnState = 1; + entry.save(); + notifyDataSetChanged(); + } else { + Toast.makeText(mContext, "添加失败1" + s + i, Toast.LENGTH_SHORT).show(); + } + } + }); + + } + }); + //同意 + } else if (entry.btnState == 1) { + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已同意"); + event.acceptGroupApproval(entry.toUsername, entry.appKey, new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + //同意加入群组 + Toast.makeText(mContext, "添加成功", Toast.LENGTH_SHORT).show(); + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已同意"); + entry.btnState = 1; + entry.save(); + notifyDataSetChanged(); + } else if (i == 856001) { + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已同意"); + } else { + Toast.makeText(mContext, "添加失败..." + s + i, Toast.LENGTH_SHORT).show(); + } + } + }); + + //拒绝 + } else if (entry.btnState == 2) { + event.refuseGroupApproval(entry.toUsername, entry.appKey, "拒绝加入", new BasicCallback() { + @Override + public void gotResult(int i, String s) { + if (i == 0) { + Toast.makeText(mContext, "拒绝成功", Toast.LENGTH_SHORT).show(); + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已拒绝"); + entry.btnState = 2; + entry.save(); + } else if (i == 856002) { + holder.item_add_btn.setBackgroundColor(Color.parseColor("#FFFFFF")); + holder.item_add_btn.setTextColor(Color.parseColor("#B5B5B6")); + holder.item_add_btn.setText("已拒绝"); + } else { + Toast.makeText(mContext, "拒绝失败" + s + i, Toast.LENGTH_SHORT).show(); + } + } + }); + + } + + + return convertView; + } + + class ViewHolder { + ImageView iv_groupAvatar; + TextView item_name; + TextView item_reason; + TextView tv_groupInvite; + TextView item_add_btn; + TextView item_state; + } + + +} diff --git a/chatapp/src/main/java/jiguang/chat/adapter/StickyListAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/StickyListAdapter.java index 16b8f3ea..4c440cef 100644 --- a/chatapp/src/main/java/jiguang/chat/adapter/StickyListAdapter.java +++ b/chatapp/src/main/java/jiguang/chat/adapter/StickyListAdapter.java @@ -43,6 +43,7 @@ import jiguang.chat.application.JGApplication; import jiguang.chat.database.FriendEntry; import jiguang.chat.utils.photochoose.SelectableRoundedImageView; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** * Created by ${chenyn} on 2017/3/16. @@ -231,7 +232,18 @@ public void gotResult(int i, String s, Bitmap bitmap) { } final long[] uid = new long[1]; - uid[0] = friend.uid; + if (friend.uid == null) { + JMessageClient.getUserInfo(friend.username, new GetUserInfoCallback() { + @Override + public void gotResult(int i, String s, UserInfo userInfo) { + if (i == 0) { + uid[0] = userInfo.getUserID(); + } + } + }); + } else { + uid[0] = friend.uid; + } if (!mIsSearch) { holder.displayName.setText(friend.displayName); } else { diff --git a/chatapp/src/main/java/jiguang/chat/adapter/StickyListHeadersAdapter.java b/chatapp/src/main/java/jiguang/chat/adapter/StickyListHeadersAdapter.java deleted file mode 100644 index d818daee..00000000 --- a/chatapp/src/main/java/jiguang/chat/adapter/StickyListHeadersAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -package jiguang.chat.adapter; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListAdapter; - -public interface StickyListHeadersAdapter extends ListAdapter { - /** - * Get a View that displays the header data at the specified position in the - * set. You can either create a View manually or inflate it from an XML layout - * file. - * - * @param position - * The position of the item within the adapter's data set of the item whose - * header view we want. - * @param convertView - * The old view to reuse, if possible. Note: You should check that this view is - * non-null and of an appropriate type before using. If it is not possible to - * convert this view to display the correct data, this method can create a new - * view. - * @param parent - * The parent that this view will eventually be attached to. - * @return - * A View corresponding to the data at the specified position. - */ - View getHeaderView(int position, View convertView, ViewGroup parent); - - /** - * Get the header id associated with the specified position in the list. - * - * @param position - * The position of the item within the adapter's data set whose header id we - * want. - * @return - * The id of the header at the specified position. - */ - long getHeaderId(int position); -} diff --git a/chatapp/src/main/java/jiguang/chat/application/JGApplication.java b/chatapp/src/main/java/jiguang/chat/application/JGApplication.java index e603d071..ceb39158 100644 --- a/chatapp/src/main/java/jiguang/chat/application/JGApplication.java +++ b/chatapp/src/main/java/jiguang/chat/application/JGApplication.java @@ -13,6 +13,7 @@ import java.util.Map; import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; @@ -76,14 +77,19 @@ public class JGApplication extends com.activeandroid.app.Application { public static final int REQUEST_CODE_SEND_LOCATION = 24; public static final int REQUEST_CODE_FRIEND_INFO = 16; public static final int RESULT_CODE_CHAT_DETAIL = 15; + public static final int REQUEST_CODE_FRIEND_LIST = 17; public static final int ON_GROUP_EVENT = 3004; public static final String DELETE_MODE = "deleteMode"; public static final int RESULT_CODE_ME_INFO = 20; public static final String DRAFT = "draft"; + public static final String CONV_TYPE = "conversationType"; //value使用 ConversationType + public static final String ROOM_ID = "roomId"; public static final String GROUP_ID = "groupId"; public static final String POSITION = "position"; public static final String MsgIDs = "msgIDs"; + public static final String MSG_JSON = "msg_json"; + public static final String MSG_LIST_JSON = "msg_list_json"; public static final String NAME = "name"; public static final String ATALL = "atall"; public static final String SEARCH_AT_MEMBER_NAME = "search_at_member_name"; @@ -96,11 +102,13 @@ public class JGApplication extends com.activeandroid.app.Application { private static final String JCHAT_CONFIGS = "JChat_configs"; public static String FILE_DIR = "sdcard/JChatDemo/recvFiles/"; public static String VIDEO_DIR = "sdcarVIDEOd/JChatDemo/sendFiles/"; + public static String THUMP_PICTURE_DIR; public static final String TARGET_ID = "targetId"; public static final String ATUSER = "atuser"; public static final String TARGET_APP_KEY = "targetAppKey"; public static int maxImgCount; //允许选择图片最大数 public static final String GROUP_NAME = "groupName"; + public static String groupAvatarPath; public static Context context; public static LocationService locationService; @@ -113,13 +121,16 @@ public class JGApplication extends com.activeandroid.app.Application { public static List alreadyRead = new ArrayList<>(); public static List unRead = new ArrayList<>(); public static List forAddFriend = new ArrayList<>(); + public static List forAddIntoGroup = new ArrayList<>(); + public static Conversation delConversation; + public static ArrayList selectedUser; @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); + THUMP_PICTURE_DIR = context.getFilesDir().getAbsolutePath() + "/JChatDemo"; StorageUtil.init(context, null); - Fresco.initialize(getApplicationContext()); SDKInitializer.initialize(getApplicationContext()); locationService = new LocationService(getApplicationContext()); diff --git a/chatapp/src/main/java/jiguang/chat/controller/ChatDetailController.java b/chatapp/src/main/java/jiguang/chat/controller/ChatDetailController.java index 4fe14a7e..3bc58f5c 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/ChatDetailController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/ChatDetailController.java @@ -1,5 +1,6 @@ package jiguang.chat.controller; +import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Intent; import android.os.Handler; @@ -17,6 +18,8 @@ import android.widget.LinearLayout; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -33,17 +36,18 @@ import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.UserInfo; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.activity.ChatDetailActivity; import jiguang.chat.activity.FriendInfoActivity; import jiguang.chat.activity.GroupAvatarActivity; -import jiguang.chat.activity.GroupGridViewActivity; +import jiguang.chat.activity.GroupMemberListActivity; import jiguang.chat.activity.GroupNotFriendActivity; +import jiguang.chat.activity.GroupUserInfoActivity; import jiguang.chat.activity.MainActivity; import jiguang.chat.activity.MembersInChatActivity; import jiguang.chat.activity.PersonalActivity; +import jiguang.chat.activity.SilenceUsersActivity; import jiguang.chat.activity.VerificationActivity; import jiguang.chat.activity.historyfile.activity.HistoryFileActivity; import jiguang.chat.adapter.GroupMemberGridAdapter; @@ -80,7 +84,7 @@ public class ChatDetailController implements OnClickListener, OnItemClickListene private Dialog mLoadingDialog = null; private static final int ADD_MEMBERS_TO_GRIDVIEW = 2048; private static final int ADD_A_MEMBER_TO_GRIDVIEW = 2049; - private static final int MAX_GRID_ITEM = 40; + private int maxGridItem = 40; private String mGroupName; private String mGroupDesc; private final MyHandler myHandler = new MyHandler(this); @@ -98,6 +102,7 @@ public class ChatDetailController implements OnClickListener, OnItemClickListene private String mAvatarPath; private boolean mFriend; private Long mUid; + private String mGroupOwnerId; public ChatDetailController(ChatDetailView chatDetailView, ChatDetailActivity context, int size, int width) { @@ -129,7 +134,10 @@ public void initData() { mGroupInfo = (GroupInfo) conv.getTargetInfo(); mChatDetailView.initNoDisturb(mGroupInfo.getNoDisturb()); mMemberInfoList = mGroupInfo.getGroupMembers(); - String groupOwnerId = mGroupInfo.getGroupOwner(); + mChatDetailView.setMemberCount(" " + mMemberInfoList.size() + " 人"); + mChatDetailView.setGroupId(mGroupId + ""); + mChatDetailView.setGroupType(mGroupInfo.getGroupFlag() == 2 ? "普通群" : "私有群"); + mGroupOwnerId = mGroupInfo.getGroupOwner(); mGroupName = mGroupInfo.getGroupName(); mGroupDesc = mGroupInfo.getGroupDescription(); if (mGroupInfo.getAvatarFile() != null && mGroupInfo.getAvatarFile().exists()) { @@ -150,9 +158,10 @@ public void initData() { } // 判断是否为群主 - if (groupOwnerId != null && groupOwnerId.equals(mMyUsername)) { + if (mGroupOwnerId != null && mGroupOwnerId.equals(mMyUsername)) { mIsCreator = true; } + maxGridItem = mIsCreator ? 13 : 14; mChatDetailView.setMyName(mMyUsername); mChatDetailView.showBlockView(mGroupInfo.isGroupBlocked()); initAdapter(); @@ -178,7 +187,6 @@ public void initData() { mChatDetailView.setAdapter(mGridAdapter); // 设置单聊界面 mChatDetailView.setSingleView(mUserInfo.isFriend()); - mChatDetailView.dismissAllMembersBtn(); mChatDetailView.isLoadMoreShow(false); JMessageClient.getUserInfo(mTargetId, new GetUserInfoCallback() { @@ -206,8 +214,8 @@ public void gotResult(int i, String s, UserInfo userInfo) { private void initAdapter() { // 初始化头像 mGridAdapter = new GroupMemberGridAdapter(mContext, mMemberInfoList, mIsCreator, mAvatarSize); - if (mMemberInfoList.size() > MAX_GRID_ITEM) { - mCurrentNum = MAX_GRID_ITEM - 1; + if (mMemberInfoList.size() > maxGridItem) { + mCurrentNum = maxGridItem; } else { mCurrentNum = mMemberInfoList.size(); } @@ -215,6 +223,7 @@ private void initAdapter() { mChatDetailView.getGridView().setFocusable(false); } + @SuppressLint("WrongConstant") @Override public void onClick(View v) { Intent intent = new Intent(); @@ -236,11 +245,11 @@ public void onClick(View v) { break; case R.id.rl_groupAvatar: intent.setClass(mContext, GroupAvatarActivity.class); - intent.putExtra("groupID",mGroupId); - if(mGroupInfo.getBigAvatarFile() != null && mGroupInfo.getBigAvatarFile().exists()) { + intent.putExtra("groupID", mGroupId); + if (mGroupInfo.getBigAvatarFile() != null && mGroupInfo.getBigAvatarFile().exists()) { intent.putExtra("groupAvatar", mGroupInfo.getBigAvatarFile().getAbsolutePath()); } - mContext.startActivityForResult(intent,4); + mContext.startActivityForResult(intent, 4); break; // 删除聊天记录 case R.id.group_chat_del_ll: @@ -298,7 +307,11 @@ public void onClick(View view) { mDialog.show(); break; case R.id.tv_moreGroup: - intent.setClass(mContext, GroupGridViewActivity.class); + case R.id.moreGroupMember: + //群成员列表,gridView + //intent.setClass(mContext, GroupGridViewActivity.class); + //群成员list列表 + intent.setClass(mContext, GroupMemberListActivity.class); intent.putExtra(JGApplication.GROUP_ID, mGroupId); intent.putExtra(JGApplication.DELETE_MODE, false); mContext.startActivityForResult(intent, JGApplication.REQUEST_CODE_ALL_MEMBER); @@ -413,6 +426,12 @@ public void onClick(View v) { mContext.startActivity(intent); mContext.overridePendingTransition(R.anim.trans_in, R.anim.trans_out); break; + //跳转群禁言列表 + case R.id.chat_silence: + intent = new Intent(mContext, SilenceUsersActivity.class); + intent.putExtra("groupID", mGroupId); + mContext.startActivity(intent); + break; } } @@ -497,16 +516,20 @@ public void onItemClick(AdapterView viewAdapter, View view, final int positio intent.setClass(mContext, PersonalActivity.class); } else { UserInfo userInfo = mMemberInfoList.get(position); + intent.setClass(mContext, GroupUserInfoActivity.class); + intent.putExtra("groupID",mGroupId); + intent.putExtra("groupUserName",userInfo.getUserName()); + intent.putExtra("groupOwner",mGroupOwnerId); //是否是好友 - if (userInfo.isFriend()) { - intent.setClass(mContext, FriendInfoActivity.class); - intent.putExtra("group_grid", true); - } else { - intent.setClass(mContext, GroupNotFriendActivity.class); - } - intent.putExtra(JGApplication.TARGET_ID, userInfo.getUserName()); - intent.putExtra(JGApplication.TARGET_APP_KEY, userInfo.getAppKey()); - intent.putExtra(JGApplication.GROUP_ID, mGroupId); +// if (userInfo.isFriend()) { +// intent.setClass(mContext, FriendInfoActivity.class); +// intent.putExtra("group_grid", true); +// } else { +// intent.setClass(mContext, GroupNotFriendActivity.class); +// } +// intent.putExtra(JGApplication.TARGET_ID, userInfo.getUserName()); +// intent.putExtra(JGApplication.TARGET_APP_KEY, userInfo.getAppKey()); +// intent.putExtra(JGApplication.GROUP_ID, mGroupId); } mContext.startActivity(intent); // 点击添加成员按钮 @@ -603,6 +626,8 @@ private void addMembers(ArrayList users) { public void gotResult(final int status, final String desc) { mLoadingDialog.dismiss(); if (status == 0) { + mMemberInfoList.clear(); + mMemberInfoList.addAll(mGroupInfo.getGroupMembers()); refreshMemberList(); } else { ToastUtil.shortToast(mContext, "添加失败"); @@ -613,7 +638,7 @@ public void gotResult(final int status, final String desc) { //添加或者删除成员后重新获得MemberInfoList public void refreshMemberList() { - mCurrentNum = mMemberInfoList.size() > MAX_GRID_ITEM ? MAX_GRID_ITEM - 1 : mMemberInfoList.size(); + mCurrentNum = mMemberInfoList.size() > maxGridItem ? maxGridItem : mMemberInfoList.size(); mGridAdapter.refreshMemberList(); } @@ -888,7 +913,10 @@ public GroupMemberGridAdapter getAdapter() { */ public void refresh(long groupId) { //当前群聊 - if (mGroupId == groupId) { + if (mGroupId == groupId && mGroupInfo != null) { + mMemberInfoList.clear(); + mMemberInfoList.addAll(mGroupInfo.getGroupMembers()); + mChatDetailView.setMemberCount(" " + mMemberInfoList.size() + " 人"); refreshMemberList(); } } diff --git a/chatapp/src/main/java/jiguang/chat/controller/ChatItemController.java b/chatapp/src/main/java/jiguang/chat/controller/ChatItemController.java index f0a03976..7d1c061e 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/ChatItemController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/ChatItemController.java @@ -13,7 +13,6 @@ import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; -import android.os.Environment; import android.support.v4.content.ContextCompat; import android.text.TextUtils; import android.view.View; @@ -58,6 +57,7 @@ import cn.jpush.im.android.api.enums.ContentType; import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.enums.MessageDirect; +import cn.jpush.im.android.api.model.ChatRoomInfo; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.android.api.model.Message; @@ -779,8 +779,29 @@ public void handleVideo(final Message msg, final ViewHolder holder, int position FileContent fileContent = (FileContent) msg.getContent(); String videoPath = fileContent.getLocalPath(); if (videoPath != null) { -// String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + msg.getServerMessageId(); - String thumbPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + msg.getServerMessageId(); + File dir = new File(JGApplication.THUMP_PICTURE_DIR); + if (!dir.exists()) { + dir.mkdirs(); + } + String thumbPath; + if (msg.getServerMessageId() == 0) { + switch (msg.getTargetType()) { + case single: + thumbPath = dir + "/" + msg.getTargetType() + "_" + ((UserInfo) msg.getTargetInfo()).getUserID() + "_" + msg.getId(); + break; + case group: + thumbPath = dir + "/" + msg.getTargetType() + "_" + ((GroupInfo) msg.getTargetInfo()).getGroupID() + "_" + msg.getId(); + break; + case chatroom: + thumbPath = dir + "/" + msg.getTargetType() + "_" + ((ChatRoomInfo) msg.getTargetInfo()).getRoomID() + "_" + msg.getId(); + break; + default: + Picasso.with(mContext).load(R.drawable.video_not_found).into(holder.picture); + return; + } + } else { + thumbPath = dir + "/" + msg.getServerMessageId(); + } String path = BitmapDecoder.extractThumbnail(videoPath, thumbPath); setPictureScale(null, msg, path, holder.picture); Picasso.with(mContext).load(new File(path)).into(holder.picture); @@ -1014,7 +1035,9 @@ public void onProgressUpdate(double v) { case receive_success: holder.progressTv.setVisibility(View.GONE); holder.contentLl.setBackground(mContext.getDrawable(R.drawable.jmui_msg_receive_bg)); - holder.fileLoad.setText("已下载"); + if (mConv.getType() != ConversationType.chatroom) { + holder.fileLoad.setText("已下载"); + } break; } } @@ -1063,6 +1086,13 @@ public void onComplete(int status, String desc, File file) { public void handleGroupChangeMsg(Message msg, ViewHolder holder) { + String extraMsg = msg.getContent().getStringExtra("msg"); + if (extraMsg != null) { // 聊天室通知事件消息 + holder.groupChange.setText(extraMsg); + holder.groupChange.setVisibility(View.VISIBLE); + holder.msgTime.setVisibility(View.GONE); + return; + } String content = ((EventNotificationContent) msg.getContent()).getEventText(); EventNotificationContent.EventNotificationType type = ((EventNotificationContent) msg .getContent()).getEventNotificationType(); @@ -1071,6 +1101,8 @@ public void handleGroupChangeMsg(Message msg, ViewHolder holder) { case group_member_exit: case group_member_removed: case group_info_updated: + case group_member_keep_silence: + case group_member_keep_silence_cancel: holder.groupChange.setText(content); holder.groupChange.setVisibility(View.VISIBLE); holder.msgTime.setVisibility(View.GONE); @@ -1089,10 +1121,14 @@ public void handleCustomMsg(Message msg, ViewHolder holder) { CustomContent content = (CustomContent) msg.getContent(); Boolean isBlackListHint = content.getBooleanValue("blackList"); Boolean notFriendFlag = content.getBooleanValue("notFriend"); - if (isBlackListHint != null && isBlackListHint) { - holder.groupChange.setText(R.string.jmui_server_803008); - holder.groupChange.setVisibility(View.VISIBLE); - } else { + //TODO:2019/04/09 会话列表滑动时自定义消息这里groupChange会出现null的情况 + if (holder.groupChange != null) { + if (isBlackListHint != null && isBlackListHint) { + holder.groupChange.setText(R.string.jmui_server_803008); + holder.groupChange.setVisibility(View.VISIBLE); + } else { + holder.groupChange.setVisibility(View.GONE); + } holder.groupChange.setVisibility(View.GONE); } @@ -1102,7 +1138,12 @@ public void handleCustomMsg(Message msg, ViewHolder holder) { // } else { // holder.groupChange.setVisibility(View.GONE); // } - holder.groupChange.setVisibility(View.GONE); + } + + public void handleUnSupportMsg(Message msg, ViewHolder holder) { + if (holder.groupChange != null) { + holder.groupChange.setText(R.string.unsupported_msg); + } } public class BtnOrTxtListener implements View.OnClickListener { @@ -1187,12 +1228,25 @@ public void onClick(View v) { case image: if (holder.picture != null && v.getId() == holder.picture.getId()) { Intent intent = new Intent(); - intent.putExtra(JGApplication.TARGET_ID, mConv.getTargetId()); + String targetId = ""; intent.putExtra("msgId", msg.getId()); - if (mConv.getType() == ConversationType.group) { - GroupInfo groupInfo = (GroupInfo) mConv.getTargetInfo(); - intent.putExtra(JGApplication.GROUP_ID, groupInfo.getGroupID()); + Object targetInfo = mConv.getTargetInfo(); + switch (mConv.getType()) { + case single: + targetId = ((UserInfo) targetInfo).getUserName(); + break; + case group: + targetId = String.valueOf(((GroupInfo) targetInfo).getGroupID()); + break; + case chatroom: + targetId = String.valueOf(((ChatRoomInfo) targetInfo).getRoomID()); + intent.putExtra(BrowserViewPagerActivity.MSG_JSON, msg.toJson()); + intent.putExtra(BrowserViewPagerActivity.MSG_LIST_JSON, getImsgMsgListJson()); + break; + default: } + intent.putExtra(JGApplication.CONV_TYPE, mConv.getType()); + intent.putExtra(JGApplication.TARGET_ID, targetId); intent.putExtra(JGApplication.TARGET_APP_KEY, mConv.getTargetAppKey()); intent.putExtra("msgCount", mMsgList.size()); intent.putIntegerArrayListExtra(JGApplication.MsgIDs, getImgMsgIDList()); @@ -1454,6 +1508,16 @@ private ArrayList getImgMsgIDList() { return imgMsgIDList; } + private String getImsgMsgListJson() { + List messages = new ArrayList<>(); + for (Message msg : mMsgList) { + if (msg.getContentType() == ContentType.image) { + messages.add(msg); + } + } + return Message.collectionToJson(messages); + } + private void browseDocument(String fileName, String path) { try { String ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); diff --git a/chatapp/src/main/java/jiguang/chat/controller/ChatRoomController.java b/chatapp/src/main/java/jiguang/chat/controller/ChatRoomController.java new file mode 100644 index 00000000..9c702e4c --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/controller/ChatRoomController.java @@ -0,0 +1,128 @@ +package jiguang.chat.controller; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.support.annotation.NonNull; +import android.view.View; +import android.widget.AdapterView; + +import com.scwang.smartrefresh.layout.api.RefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; +import com.scwang.smartrefresh.layout.listener.OnRefreshListener; + +import java.util.ArrayList; +import java.util.List; + +import cn.jpush.im.android.api.ChatRoomManager; +import cn.jpush.im.android.api.callback.RequestCallback; +import cn.jpush.im.android.api.enums.ConversationType; +import cn.jpush.im.android.api.model.ChatRoomInfo; +import jiguang.chat.R; +import jiguang.chat.activity.ChatActivity; +import jiguang.chat.activity.SearchChatRoomActivity; +import jiguang.chat.adapter.ChatRoomAdapter; +import jiguang.chat.application.JGApplication; +import jiguang.chat.utils.DialogCreator; +import jiguang.chat.utils.HandleResponseCode; +import jiguang.chat.view.ChatRoomView; + +/** + * Created by ${chenyn} on 2017/10/31. + */ + +public class ChatRoomController implements AdapterView.OnItemClickListener, View.OnClickListener, OnRefreshListener, OnLoadMoreListener { + private ChatRoomView mChatRoomView; + private Context mContext; + private static final int PAGE_COUNT = 15; + private List chatRoomInfos = new ArrayList<>(); + private ChatRoomAdapter chatRoomAdapter; + + public ChatRoomController(ChatRoomView chatRoomView, Context context) { + this.mChatRoomView = chatRoomView; + this.mContext = context; + initChatRoomAdapter(); + } + + private void initChatRoomAdapter() { + Dialog loadingDialog = DialogCreator.createLoadingDialog(mContext, "正在加载..."); + loadingDialog.show(); + ChatRoomManager.getChatRoomListByApp(0, PAGE_COUNT, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List result) { + loadingDialog.dismiss(); + if (i == 0) { + chatRoomInfos.addAll(result); + } else { + HandleResponseCode.onHandle(mContext, i, false); + } + chatRoomAdapter = new ChatRoomAdapter(mContext, chatRoomInfos, mChatRoomView); + mChatRoomView.setChatRoomAdapter(chatRoomAdapter); + mChatRoomView.setNullChatRoom(chatRoomInfos.size() == 0); + } + }); + } + + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + Object itemAtPosition = parent.getItemAtPosition(position); + if (itemAtPosition != null && itemAtPosition instanceof ChatRoomInfo) { + ChatRoomInfo info = (ChatRoomInfo) itemAtPosition; + Intent intent = new Intent(mContext, ChatActivity.class); + intent.putExtra(JGApplication.CONV_TYPE, ConversationType.chatroom); + intent.putExtra("chatRoomId", info.getRoomID()); + intent.putExtra("chatRoomName", info.getName()); + mContext.startActivity(intent); + } + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.search_title) { + Intent intent = new Intent(mContext, SearchChatRoomActivity.class); + mContext.startActivity(intent); + } + } + + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + mChatRoomView.setNullChatRoom(false); + ChatRoomManager.getChatRoomListByApp(0, PAGE_COUNT, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List result) { + if (i == 0) { + chatRoomInfos.clear(); + chatRoomInfos.addAll(result); + mChatRoomView.setNullChatRoom(chatRoomInfos.size() == 0); + if (chatRoomAdapter != null) { + chatRoomAdapter.notifyDataSetChanged(); + } + } else { + HandleResponseCode.onHandle(mContext, i, false); + } + refreshLayout.finishRefresh(); + } + }); + } + + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + mChatRoomView.setNullChatRoom(false); + ChatRoomManager.getChatRoomListByApp(chatRoomInfos.size(), PAGE_COUNT, new RequestCallback>() { + @Override + public void gotResult(int i, String s, List result) { + if (i == 0) { + chatRoomInfos.addAll(result); + mChatRoomView.setNullChatRoom(chatRoomInfos.size() == 0); + if (chatRoomAdapter != null) { + chatRoomAdapter.notifyDataSetChanged(); + } + } else { + HandleResponseCode.onHandle(mContext, i, false); + } + refreshLayout.finishLoadMore(); + } + }); + } +} diff --git a/chatapp/src/main/java/jiguang/chat/controller/ContactsController.java b/chatapp/src/main/java/jiguang/chat/controller/ContactsController.java index 203de349..434ac03a 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/ContactsController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/ContactsController.java @@ -5,6 +5,7 @@ import android.support.v4.app.FragmentActivity; import android.text.TextUtils; import android.view.View; +import android.widget.TextView; import com.activeandroid.ActiveAndroid; @@ -17,10 +18,10 @@ import cn.jpush.im.android.api.callback.GetUserInfoListCallback; import cn.jpush.im.android.api.model.UserInfo; import jiguang.chat.R; -import jiguang.chat.activity.FriendRecommendActivity; import jiguang.chat.activity.GroupActivity; import jiguang.chat.activity.SearchContactsActivity; import jiguang.chat.activity.SearchForAddFriendActivity; +import jiguang.chat.activity.VerificationMessageActivity; import jiguang.chat.adapter.StickyListAdapter; import jiguang.chat.application.JGApplication; import jiguang.chat.database.FriendEntry; @@ -39,12 +40,14 @@ public class ContactsController implements View.OnClickListener, SideBar.OnTouch private Activity mContext; private List mList = new ArrayList<>(); private StickyListAdapter mAdapter; + private TextView mAllContactNumber; private List forDelete = new ArrayList<>(); public ContactsController(ContactsView mContactsView, FragmentActivity context) { this.mContactsView = mContactsView; this.mContext = context; + mAllContactNumber = mContext.findViewById(R.id.all_contact_number); } @@ -57,9 +60,11 @@ public void onClick(View v) { mContext.startActivity(intent); break; case R.id.verify_ll://验证消息 - intent.setClass(mContext, FriendRecommendActivity.class); + //intent.setClass(mContext, FriendRecommendActivity.class); + intent.setClass(mContext, VerificationMessageActivity.class); mContext.startActivity(intent); mContactsView.dismissNewFriends(); + mAllContactNumber.setVisibility(View.GONE); break; case R.id.group_ll://群组 intent.setClass(mContext, GroupActivity.class); @@ -84,7 +89,7 @@ public void initContacts() { public void gotResult(int responseCode, String responseMessage, List userInfoList) { mContactsView.dismissLoadingHeader(); if (responseCode == 0) { - if (userInfoList.size() != 0) { + if (userInfoList != null && userInfoList.size() != 0) { mContactsView.dismissLine(); ActiveAndroid.beginTransaction(); try { diff --git a/chatapp/src/main/java/jiguang/chat/controller/ConversationListController.java b/chatapp/src/main/java/jiguang/chat/controller/ConversationListController.java index 49590e39..442ab72c 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/ConversationListController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/ConversationListController.java @@ -64,7 +64,8 @@ private void initConvListAdapter() { SortConvList sortConvList = new SortConvList(); Collections.sort(mDatas, sortConvList); for (Conversation con : mDatas) { - if (con.getTargetId().equals("feedback_Android")) { + //如果会话有聊天室会话就把这会话删除 + if (con.getTargetId().equals("feedback_Android") || con.getType().equals(ConversationType.chatroom)) { delFeedBack.add(con); } if (!TextUtils.isEmpty(con.getExtra())) { @@ -129,7 +130,7 @@ public void onItemClick(AdapterView parent, View view, int position, long id) mContext.getActivity().startActivity(intent); return; //单聊 - } else { + } else if (conv.getType() == ConversationType.single) { String targetId = ((UserInfo) conv.getTargetInfo()).getUserName(); intent.putExtra(JGApplication.TARGET_ID, targetId); intent.putExtra(JGApplication.TARGET_APP_KEY, conv.getTargetAppKey()); @@ -192,4 +193,7 @@ public void onClick(View v) { } return true; } + public void delConversation() { + mDatas.remove(JGApplication.delConversation); + } } diff --git a/chatapp/src/main/java/jiguang/chat/controller/FriendInfoController.java b/chatapp/src/main/java/jiguang/chat/controller/FriendInfoController.java index 745d1400..1b0afbe5 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/FriendInfoController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/FriendInfoController.java @@ -7,7 +7,6 @@ import jiguang.chat.R; import jiguang.chat.activity.FriendInfoActivity; import jiguang.chat.activity.FriendSettingActivity; -import jiguang.chat.view.FriendInfoView; /** * Created by ${chenyn} on 2017/3/24. @@ -16,9 +15,11 @@ public class FriendInfoController implements View.OnClickListener { private FriendInfoActivity mContext; private UserInfo friendInfo; + private int flags; - public FriendInfoController(FriendInfoView friendInfoView, FriendInfoActivity context) { + public FriendInfoController(int flags, FriendInfoActivity context) { this.mContext = context; + this.flags = flags; } @Override @@ -31,7 +32,8 @@ public void onClick(View v) { mContext.startBrowserAvatar(); break; case R.id.jmui_commit_btn: - Intent intent = new Intent(mContext, FriendSettingActivity.class); + Intent intent = new Intent(); + intent.setClass(mContext, FriendSettingActivity.class); intent.putExtra("userName", friendInfo.getUserName()); intent.putExtra("noteName", friendInfo.getNotename()); mContext.startActivity(intent); diff --git a/chatapp/src/main/java/jiguang/chat/controller/MainController.java b/chatapp/src/main/java/jiguang/chat/controller/MainController.java index de31ee54..acafdec8 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/MainController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/MainController.java @@ -9,6 +9,7 @@ import jiguang.chat.R; import jiguang.chat.activity.MainActivity; +import jiguang.chat.activity.fragment.ChatRoomFragment; import jiguang.chat.activity.fragment.ContactsFragment; import jiguang.chat.activity.fragment.ConversationListFragment; import jiguang.chat.activity.fragment.MeFragment; @@ -25,6 +26,7 @@ public class MainController implements View.OnClickListener, ViewPager.OnPageCha private ConversationListFragment mConvListFragment; private MeFragment mMeFragment; private ContactsFragment mContactsFragment; + private ChatRoomFragment mChatRoomFragment; public MainController(MainView mMainView, MainActivity context) { @@ -37,10 +39,12 @@ private void setViewPager() { final List fragments = new ArrayList<>(); // init Fragment mConvListFragment = new ConversationListFragment(); + mChatRoomFragment = new ChatRoomFragment(); mContactsFragment = new ContactsFragment(); mMeFragment = new MeFragment(); fragments.add(mConvListFragment); + fragments.add(mChatRoomFragment); fragments.add(mContactsFragment); fragments.add(mMeFragment); ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(mContext.getSupportFragmentManger(), @@ -51,17 +55,19 @@ private void setViewPager() { @Override public void onClick(View v) { - // TODO Auto-generated method stub switch (v.getId()) { case R.id.actionbar_msg_btn: mMainView.setCurrentItem(0, false); break; - case R.id.actionbar_contact_btn: + case R.id.actionbar_chatroom_btn: mMainView.setCurrentItem(1, false); break; - case R.id.actionbar_me_btn: + case R.id.actionbar_contact_btn: mMainView.setCurrentItem(2, false); break; + case R.id.actionbar_me_btn: + mMainView.setCurrentItem(3, false); + break; } } diff --git a/chatapp/src/main/java/jiguang/chat/controller/MenuItemController.java b/chatapp/src/main/java/jiguang/chat/controller/MenuItemController.java index e29e54ee..9659e0de 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/MenuItemController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/MenuItemController.java @@ -4,6 +4,7 @@ import android.view.View; import jiguang.chat.R; +import jiguang.chat.activity.SearchAddOpenGroupActivity; import jiguang.chat.activity.CommonScanActivity; import jiguang.chat.activity.CreateGroupActivity; import jiguang.chat.activity.SearchForAddFriendActivity; @@ -49,6 +50,11 @@ public void onClick(View v) { intent.putExtra(Constant.REQUEST_SCAN_MODE, Constant.REQUEST_SCAN_MODE_QRCODE_MODE); mFragment.getContext().startActivity(intent); break; + //加入公开群 + case R.id.add_open_group: + intent = new Intent(mFragment.getContext(), SearchAddOpenGroupActivity.class); + mFragment.getContext().startActivity(intent); + break; default: break; } diff --git a/chatapp/src/main/java/jiguang/chat/controller/SendFileController.java b/chatapp/src/main/java/jiguang/chat/controller/SendFileController.java index d739069a..aadaf64e 100644 --- a/chatapp/src/main/java/jiguang/chat/controller/SendFileController.java +++ b/chatapp/src/main/java/jiguang/chat/controller/SendFileController.java @@ -15,6 +15,7 @@ import java.lang.ref.WeakReference; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -24,6 +25,7 @@ import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.content.FileContent; import cn.jpush.im.android.api.content.ImageContent; +import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.exceptions.JMFileSizeExceedException; import cn.jpush.im.android.api.model.Conversation; import cn.jpush.im.android.api.model.Message; @@ -61,7 +63,7 @@ public class SendFileController implements View.OnClickListener, ViewPager.OnPag private int mSize; private final static int SEND_FILE = 0x4001; private MyHandler myHandler = new MyHandler(this); - private int[] mMsgIds; + private Message[] mMsgs; public SendFileController(SendFileActivity context, SendFileView view) { @@ -90,11 +92,17 @@ public SendFileController(SendFileActivity context, SendFileView view) { String targetId = mContext.getIntent().getStringExtra(JGApplication.TARGET_ID); String targetAppKey = mContext.getIntent().getStringExtra(JGApplication.TARGET_APP_KEY); - long groupId = mContext.getIntent().getLongExtra(JGApplication.GROUP_ID, 0); - if (groupId != 0) { - mConv = JMessageClient.getGroupConversation(groupId); - } else { - mConv = JMessageClient.getSingleConversation(targetId, targetAppKey); + ConversationType convType = (ConversationType) mContext.getIntent().getSerializableExtra(JGApplication.CONV_TYPE); + switch (convType) { + case single: + mConv = JMessageClient.getSingleConversation(targetId, targetAppKey); + break; + case group: + mConv = JMessageClient.getGroupConversation(Long.valueOf(targetId)); + break; + case chatroom: + mConv = JMessageClient.getChatRoomConversation(Long.valueOf(targetId)); + } } @@ -144,7 +152,7 @@ public void onClick(View view) { mDialog.setMessage(mContext.getString(R.string.sending_hint)); mDialog.show(); Iterator>> iterator = mFileMap.entrySet().iterator(); - mMsgIds = new int[mSize]; + mMsgs = new Message[mSize]; while (iterator.hasNext()) { final Map.Entry> entry = iterator.next(); ArrayList list = entry.getValue(); @@ -159,9 +167,9 @@ public void onClick(View view) { public void gotResult(int status, String desc, ImageContent imageContent) { if (status == 0) { Message msg = mConv.createSendMessage(imageContent); - mMsgIds[mIndex.get()] = msg.getId(); + mMsgs[mIndex.get()] = msg; } else { - mMsgIds[mIndex.get()] = -1; + mMsgs[mIndex.get()] = null; } mIndex.incrementAndGet(); if (mIndex.get() >= mSize) { @@ -176,9 +184,9 @@ public void gotResult(int status, String desc, ImageContent imageContent) { public void gotResult(int status, String desc, ImageContent imageContent) { if (status == 0) { Message msg = mConv.createSendMessage(imageContent); - mMsgIds[mIndex.get()] = msg.getId(); + mMsgs[mIndex.get()] = msg; } else { - mMsgIds[mIndex.get()] = -1; + mMsgs[mIndex.get()] = null; } mIndex.incrementAndGet(); if (mIndex.get() >= mSize) { @@ -204,7 +212,7 @@ public void gotResult(int status, String desc, ImageContent imageContent) { content.setNumberExtra("fileSize", file.length()); Message msg = mConv.createSendMessage(content); if (mIndex.get() < mSize) { - mMsgIds[mIndex.get()] = msg.getId(); + mMsgs[mIndex.get()] = msg; mIndex.incrementAndGet(); if (mIndex.get() >= mSize) { myHandler.sendEmptyMessage(SEND_FILE); @@ -310,7 +318,7 @@ public void handleMessage(android.os.Message msg) { switch (msg.what) { case SEND_FILE: Intent intent = new Intent(); - intent.putExtra(JGApplication.MsgIDs, controller.mMsgIds); + intent.putExtra(JGApplication.MSG_LIST_JSON, Message.collectionToJson(Arrays.asList(controller.mMsgs))); controller.mContext.setResult(JGApplication.RESULT_CODE_SEND_FILE, intent); if (controller.mDialog != null) { controller.mDialog.dismiss(); diff --git a/chatapp/src/main/java/jiguang/chat/database/ConversationEntry.java b/chatapp/src/main/java/jiguang/chat/database/ConversationEntry.java deleted file mode 100644 index 1dc5aacf..00000000 --- a/chatapp/src/main/java/jiguang/chat/database/ConversationEntry.java +++ /dev/null @@ -1,36 +0,0 @@ -package jiguang.chat.database; - -/** - * Created by ${chenyn} on 2017/7/18. - */ - -import com.activeandroid.Model; -import com.activeandroid.annotation.Column; -import com.activeandroid.annotation.Table; -import com.activeandroid.query.Select; - -@Table(name = "conversation", id = "_id") -public class ConversationEntry extends Model{ - - @Column(name = "Targetname") - public String targetname; - - @Column(name = "Orders") - public Integer order; - - - public ConversationEntry(){ - super(); - } - - public ConversationEntry(String targetname, int order) { - super(); - this.targetname = targetname; - this.order = order; - } - - public static ConversationEntry getTopConversation(int order) { - return new Select().from(ConversationEntry.class) - .where("Orders = ?", order).executeSingle(); - } -} diff --git a/chatapp/src/main/java/jiguang/chat/database/GroupApplyEntry.java b/chatapp/src/main/java/jiguang/chat/database/GroupApplyEntry.java new file mode 100644 index 00000000..f03d84b7 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/database/GroupApplyEntry.java @@ -0,0 +1,91 @@ +package jiguang.chat.database; + +/** + * Created by ${chenyn} on 2017/7/18. + */ + +import com.activeandroid.Model; +import com.activeandroid.annotation.Column; +import com.activeandroid.annotation.Table; +import com.activeandroid.query.Delete; +import com.activeandroid.query.Select; + +@Table(name = "group_apply", id = "_id") +public class GroupApplyEntry extends Model { + + @Column(name = "FromUsername") + public String fromUsername; + + @Column(name = "ToUsername") + public String toUsername; + + @Column(name = "AppKey") + public String appKey; + + @Column(name = "Avatar") + public String Avatar; + + @Column(name = "FromDisplayName") + public String fromDisplayName; + + @Column(name = "toDisplayName") + public String toDisplayName; + + @Column(name = "Reason") + public String reason; + + @Column(name = "State") + public String state; + + @Column(name = "EventJson") + public String eventJson; + + @Column(name = "GroupName") + public String groupName; + + @Column(name = "User") + public UserEntry user; + + @Column(name = "BtnState") + public int btnState; + + @Column(name = "GroupType") + public int groupType; + + public GroupApplyEntry() { + super(); + } + + public GroupApplyEntry(String fromUsername, String toUsername, String appKey, String Avatar, String fromDisplayName, String toDisplayName, + String reason, String state, String eventJson, String groupName, UserEntry user, int btnState, int groupType) { + super(); + this.fromUsername = fromUsername; + this.toUsername = toUsername; + this.appKey = appKey; + this.Avatar = Avatar; + this.fromDisplayName = fromDisplayName; + this.toDisplayName = toDisplayName; + this.reason = reason; + this.state = state; + this.eventJson = eventJson; + this.groupName = groupName; + this.user = user; + this.btnState = btnState; + this.groupType = groupType; + } + + public static GroupApplyEntry getEntry(UserEntry user, String username, String appKey) { + return new Select().from(GroupApplyEntry.class).where("ToUsername = ?", username) + .where("AppKey = ?", appKey) + .where("User = ?", user.getId()).executeSingle(); + } + + public static GroupApplyEntry getEntry(long id) { + return new Select().from(GroupApplyEntry.class).where("_id = ?", id).executeSingle(); + } + + public static void deleteEntry(GroupApplyEntry entry) { + new Delete().from(GroupApplyEntry.class).where("_id = ?", entry.getId()).execute(); + } + +} diff --git a/chatapp/src/main/java/jiguang/chat/database/RefuseGroupEntry.java b/chatapp/src/main/java/jiguang/chat/database/RefuseGroupEntry.java new file mode 100644 index 00000000..19e532d8 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/database/RefuseGroupEntry.java @@ -0,0 +1,52 @@ +package jiguang.chat.database; + +import com.activeandroid.Model; +import com.activeandroid.annotation.Column; +import com.activeandroid.annotation.Table; +import com.activeandroid.query.Select; + +/** + * Created by ${chenyn} on 2017/11/24. + */ + +@Table(name = "refuse_group", id = "_id") +public class RefuseGroupEntry extends Model { + + @Column(name = "Username") + public String username; + + @Column(name = "DisplayName") + public String displayName; + + @Column(name = "GroupId") + public String groupId; + + @Column(name = "AppKey") + public String appKey; + + @Column(name = "Avatar") + public String avatar; + + @Column(name = "User") + public UserEntry user; + + public RefuseGroupEntry() {} + + public RefuseGroupEntry(UserEntry user, String username, String displayName, String groupId, String appKey, String avatar) { + super(); + this.user = user; + this.username = username; + this.displayName = displayName; + this.groupId = groupId; + this.appKey = appKey; + this.avatar = avatar; + } + + public static RefuseGroupEntry getEntry(UserEntry user, String username, String appKey) { + return new Select().from(RefuseGroupEntry.class).where("Username = ?", username) + .where("AppKey = ?", appKey) + .where("User = ?", user.getId()).executeSingle(); + } + + +} diff --git a/chatapp/src/main/java/jiguang/chat/database/UserEntry.java b/chatapp/src/main/java/jiguang/chat/database/UserEntry.java index fb12073a..d01247e4 100644 --- a/chatapp/src/main/java/jiguang/chat/database/UserEntry.java +++ b/chatapp/src/main/java/jiguang/chat/database/UserEntry.java @@ -36,6 +36,14 @@ public List getRecommends() { return getMany(FriendRecommendEntry.class, "User"); } + public List getGroupApplyRecommends() { + return getMany(GroupApplyEntry.class, "User"); + } + + public List getRefuseGroupRecommends() { + return getMany(RefuseGroupEntry.class, "User"); + } + public List getFriends() { return getMany(FriendEntry.class, "User"); } diff --git a/chatapp/src/main/java/jiguang/chat/entity/GroupApplyInvitation.java b/chatapp/src/main/java/jiguang/chat/entity/GroupApplyInvitation.java new file mode 100644 index 00000000..9100b406 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/entity/GroupApplyInvitation.java @@ -0,0 +1,21 @@ +package jiguang.chat.entity; + +public enum GroupApplyInvitation { + ACCEPTED("accepted"),//已接受 + INVITING("inviting"), + INVITED("invited"), + REFUSED("refused"), + BE_REFUSED("be_refused"), + DEFAULT("default"); + + + private String value; + + GroupApplyInvitation(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/location/activity/MapPickerActivity.java b/chatapp/src/main/java/jiguang/chat/location/activity/MapPickerActivity.java index 7f149ac3..83e3f1c6 100755 --- a/chatapp/src/main/java/jiguang/chat/location/activity/MapPickerActivity.java +++ b/chatapp/src/main/java/jiguang/chat/location/activity/MapPickerActivity.java @@ -50,6 +50,7 @@ import java.util.UUID; import cn.jpush.im.android.api.JMessageClient; +import cn.jpush.im.android.api.enums.ConversationType; import cn.jpush.im.android.api.model.Conversation; import jiguang.chat.R; import jiguang.chat.application.JGApplication; @@ -123,14 +124,23 @@ protected void onCreate(Bundle savedInstanceState) { initMap(); initIntent(); + ConversationType convType = (ConversationType) getIntent().getSerializableExtra(JGApplication.CONV_TYPE); String targetId = getIntent().getStringExtra(JGApplication.TARGET_ID); String targetAppKey = getIntent().getStringExtra(JGApplication.TARGET_APP_KEY); - long groupId = getIntent().getLongExtra(JGApplication.GROUP_ID, 0); - - if (groupId != 0) { - conv = JMessageClient.getGroupConversation(groupId); - } else { - conv = JMessageClient.getSingleConversation(targetId, targetAppKey); + if (convType != null) { + switch (convType) { + case single: + conv = JMessageClient.getSingleConversation(targetId, targetAppKey); + break; + case group: + conv = JMessageClient.getGroupConversation(Long.valueOf(targetId)); + break; + case chatroom: + conv = JMessageClient.getChatRoomConversation(Long.valueOf(targetId)); + break; + default: + break; + } } diff --git a/chatapp/src/main/java/jiguang/chat/utils/DialogCreator.java b/chatapp/src/main/java/jiguang/chat/utils/DialogCreator.java index 036605dd..1d24401d 100644 --- a/chatapp/src/main/java/jiguang/chat/utils/DialogCreator.java +++ b/chatapp/src/main/java/jiguang/chat/utils/DialogCreator.java @@ -19,6 +19,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; + import cn.jpush.im.android.api.JMessageClient; import cn.jpush.im.android.api.content.FileContent; import cn.jpush.im.android.api.content.ImageContent; @@ -30,7 +32,6 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; -import cn.jpush.im.android.eventbus.EventBus; import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.application.JGApplication; diff --git a/chatapp/src/main/java/jiguang/chat/utils/FileHelper.java b/chatapp/src/main/java/jiguang/chat/utils/FileHelper.java index fe94a01b..ebafa2af 100644 --- a/chatapp/src/main/java/jiguang/chat/utils/FileHelper.java +++ b/chatapp/src/main/java/jiguang/chat/utils/FileHelper.java @@ -73,7 +73,6 @@ public void run() { destDir.mkdirs(); } final File tempFile = new File(JGApplication.FILE_DIR + fileName); - System.out.println("=================" + tempFile.exists() + tempFile.isFile()); FileOutputStream fos = new FileOutputStream(tempFile); byte[] bt = new byte[1024]; int c; diff --git a/chatapp/src/main/java/jiguang/chat/utils/GroupMemberListComparator.java b/chatapp/src/main/java/jiguang/chat/utils/GroupMemberListComparator.java new file mode 100644 index 00000000..fae3fb78 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/utils/GroupMemberListComparator.java @@ -0,0 +1,49 @@ +package jiguang.chat.utils; + +import java.util.ArrayList; +import java.util.Comparator; + +import cn.jpush.im.android.api.model.UserInfo; +import jiguang.chat.utils.pinyin.HanziToPinyin; + +/** + * Created by ${chenyn} on 2017/11/3. + */ + +public class GroupMemberListComparator implements Comparator{ + @Override + public int compare(UserInfo o1, UserInfo o2) { + if (getLetter(o1.getDisplayName()).equals("@") || + getLetter(o2.getDisplayName()).equals("#")) { + return -1; + }else if (getLetter(o1.getDisplayName()).equals("#") + || getLetter(o2.getDisplayName()).equals("@")) { + return 1; + }else { + return getLetter(o1.getDisplayName()).compareTo(getLetter(o2.getDisplayName())); + } + } + + public String getLetter(String name) { + String letter; + ArrayList tokens = HanziToPinyin.getInstance() + .get(name); + StringBuilder sb = new StringBuilder(); + if (tokens != null && tokens.size() > 0) { + for (HanziToPinyin.Token token : tokens) { + if (token.type == HanziToPinyin.Token.PINYIN) { + sb.append(token.target); + } else { + sb.append(token.source); + } + } + } + String sortString = sb.toString().substring(0, 1).toUpperCase(); + if (sortString.matches("[A-Z]")) { + letter = sortString.toUpperCase(); + } else { + letter = "#"; + } + return letter; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/utils/ThreadUtil.java b/chatapp/src/main/java/jiguang/chat/utils/ThreadUtil.java index 0cc8b97c..5650735c 100644 --- a/chatapp/src/main/java/jiguang/chat/utils/ThreadUtil.java +++ b/chatapp/src/main/java/jiguang/chat/utils/ThreadUtil.java @@ -2,13 +2,14 @@ import android.os.Handler; +import android.os.Looper; /** * Created by ${chenyn} on 2017/3/10. */ public class ThreadUtil { - static Handler mHandler = new Handler(); + static Handler mHandler = new Handler(Looper.getMainLooper()); public static void runInThread(Runnable task) { new Thread(task).start(); diff --git a/chatapp/src/main/java/jiguang/chat/utils/photochoose/ChoosePhoto.java b/chatapp/src/main/java/jiguang/chat/utils/photochoose/ChoosePhoto.java index e88ab9a9..268be69e 100644 --- a/chatapp/src/main/java/jiguang/chat/utils/photochoose/ChoosePhoto.java +++ b/chatapp/src/main/java/jiguang/chat/utils/photochoose/ChoosePhoto.java @@ -16,6 +16,7 @@ import cn.jpush.im.android.api.model.GroupInfo; import cn.jpush.im.api.BasicCallback; import jiguang.chat.activity.PersonalActivity; +import jiguang.chat.application.JGApplication; import jiguang.chat.utils.HandleResponseCode; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.ToastUtil; @@ -137,4 +138,19 @@ public void onPhotoCancel() { }); } + public void getCreateGroupAvatar(ImageView iv_groupAvatar) { + photoUtils = new PhotoUtils(new PhotoUtils.OnPhotoResultListener() { + @Override + public void onPhotoResult(Uri uri) { + iv_groupAvatar.setImageBitmap(BitmapFactory.decodeFile(uri.getPath())); + JGApplication.groupAvatarPath = uri.getPath(); + } + + @Override + public void onPhotoCancel() { + + } + }); + } + } diff --git a/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/camera/CameraManager.java b/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/camera/CameraManager.java index 91435b90..91edf647 100755 --- a/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/camera/CameraManager.java +++ b/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/camera/CameraManager.java @@ -1,503 +1,506 @@ -package jiguang.chat.utils.photovideo.takevideo.camera; - -import android.app.Application; -import android.content.Context; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.media.CamcorderProfile; -import android.media.MediaRecorder; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; - -import jiguang.chat.utils.photovideo.takevideo.utils.LogUtils; - - -/** - * 相机管理类 - */ - -public final class CameraManager { - - private Application context; - /** - * camera - */ - private Camera mCamera; - /** - * 视频录制 - */ - private MediaRecorder mMediaRecorder; - /** - * 相机闪光状态 - */ - private int cameraFlash; - /** - * 前后置状态 - */ - private int cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; - /** - * 是否支持前置摄像,是否支持闪光 - */ - private boolean isSupportFrontCamera, isSupportFlashCamera; - /** - * 录制视频的相关参数 - */ - private CamcorderProfile mProfile; - /** - * 0为拍照, 1为录像 - */ - private int cameraType; - - private CameraManager(Application context) { - this.context = context; - isSupportFrontCamera = CameraUtils.isSupportFrontCamera(); - isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context); - if (isSupportFrontCamera) { - cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK); - } - if (isSupportFlashCamera) { - cameraFlash = CameraUtils.getCameraFlash(context); - } - } - - private static CameraManager INSTANCE; - - public static CameraManager getInstance(Application context) { - if (INSTANCE == null) { - synchronized (CameraManager.class) { - if (INSTANCE == null) { - INSTANCE = new CameraManager(context); - } - } - } - return INSTANCE; - } - - /** - * 打开camera - */ - public void openCamera(Context context, SurfaceTexture surfaceTexture, int width, int height) { - if (mCamera == null) { - try { - mCamera = Camera.open(cameraFacing);//打开当前选中的摄像头 - mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH); - mCamera.setDisplayOrientation(90);//默认竖直拍照 - mCamera.setPreviewTexture(surfaceTexture); - initCameraParameters(cameraFacing, width, height); - mCamera.startPreview(); - } catch (Exception e) { - if (mCamera != null) { - mCamera.release(); - mCamera = null; - } - } - } - } - - - /** - * 开启预览,前提是camera初始化了 - */ - public void restartPreview() { - if (mCamera == null) return; - try { - Camera.Parameters parameters = mCamera.getParameters(); - int zoom = parameters.getZoom(); - if (zoom > 0) { - parameters.setZoom(0); - mCamera.setParameters(parameters); - } - mCamera.startPreview(); - } catch (Exception e) { - LogUtils.i(e); - if (mCamera != null) { - mCamera.release(); - mCamera = null; - } - } - } - - private void initCameraParameters(int cameraId, int width, int height) { - Camera.Parameters parameters = mCamera.getParameters(); - if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { - List focusModes = parameters.getSupportedFocusModes(); - if (focusModes != null) { - if (cameraType == 0) { - if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { - parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); - } - } else { - if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - } - } - } - } - parameters.setRotation(90);//设置旋转代码, - switch (cameraFlash) { - case 0: - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); - break; - case 1: - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); - break; - case 2: - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - break; - } - List pictureSizes = parameters.getSupportedPictureSizes(); - List previewSizes = parameters.getSupportedPreviewSizes(); - if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) { - /*for (Camera.Size size : pictureSizes) { - LogUtils.i("pictureSize " + size.width + " " + size.height); - } - for (Camera.Size size : pictureSizes) { - LogUtils.i("previewSize " + size.width + " " + size.height); - }*/ - Camera.Size optimalPicSize = getOptimalSize(pictureSizes, width, height); - Camera.Size optimalPreSize = getOptimalSize(previewSizes, width, height); - LogUtils.i("TextureSize " + width + " " + height + " optimalSize pic " + optimalPicSize.width + " " + optimalPicSize.height + " pre " + optimalPreSize.width + " " + optimalPreSize.height); - parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height); - parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height); - mProfile.videoFrameWidth = optimalPreSize.width; - mProfile.videoFrameHeight = optimalPreSize.height; - mProfile.videoBitRate = 5000000;//此参数主要决定视频拍出大小 - } - mCamera.setParameters(parameters); - } - - /** - * 释放摄像头 - */ - public void closeCamera() { - this.cameraType = 0; - if (mCamera != null) { - try { - mCamera.stopPreview(); - mCamera.release(); - mCamera = null; - } catch (Exception e) { - LogUtils.i(e); - if (mCamera != null) { - mCamera.release(); - mCamera = null; - } - } - } - } - - /** - * 集合不为空 - * - * @param list - * @param - * @return - */ - private boolean isEmpty(List list) { - return list == null || list.isEmpty(); - } - - /** - * 获取最佳预览相机Size参数 - * - * @return - */ - private Camera.Size getOptimalSize(List sizes, int w, int h) { - Camera.Size optimalSize = null; - float targetRadio = h / (float) w; - float optimalDif = Float.MAX_VALUE; //最匹配的比例 - int optimalMaxDif = Integer.MAX_VALUE;//最优的最大值差距 - for (Camera.Size size : sizes) { - float newOptimal = size.width / (float) size.height; - float newDiff = Math.abs(newOptimal - targetRadio); - if (newDiff < optimalDif) { //更好的尺寸 - optimalDif = newDiff; - optimalSize = size; - optimalMaxDif = Math.abs(h - size.width); - } else if (newDiff == optimalDif) {//更好的尺寸 - int newOptimalMaxDif = Math.abs(h - size.width); - if (newOptimalMaxDif < optimalMaxDif) { - optimalDif = newDiff; - optimalSize = size; - optimalMaxDif = newOptimalMaxDif; - } - } - } - return optimalSize; - } - - /** - * 缩放 - * - * @param isZoomIn - */ - public void handleZoom(boolean isZoomIn) { - if (mCamera == null) return; - Camera.Parameters params = mCamera.getParameters(); - if (params == null) return; - if (params.isZoomSupported()) { - int maxZoom = params.getMaxZoom(); - int zoom = params.getZoom(); - if (isZoomIn && zoom < maxZoom) { - zoom++; - } else if (zoom > 0) { - zoom--; - } - params.setZoom(zoom); - mCamera.setParameters(params); - } else { - LogUtils.i("zoom not supported"); - } - } - - /** - * 更换前后置摄像 - */ - public void changeCameraFacing(Context context, SurfaceTexture surfaceTexture, int width, int height) { - if (isSupportFrontCamera) { - Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); - int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 - for (int i = 0; i < cameraCount; i++) { - Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息 - if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //现在是后置,变更为前置 - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位为前置 - closeCamera(); - cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; - CameraUtils.setCameraFacing(context, cameraFacing); - openCamera(context, surfaceTexture, width, height); - break; - } - } else {//现在是前置, 变更为后置 - if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位 - closeCamera(); - cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT; - CameraUtils.setCameraFacing(context, cameraFacing); - openCamera(context, surfaceTexture, width, height); - break; - } - } - } - } else { //不支持摄像机 - Toast.makeText(context, "您的手机不支持前置摄像", Toast.LENGTH_SHORT).show(); - } - } - - /** - * 改变闪光状态 - */ - public void changeCameraFlash(SurfaceTexture surfaceTexture, int width, int height) { - if (!isSupportFlashCamera) { - Toast.makeText(context, "您的手机不支闪光", Toast.LENGTH_SHORT).show(); - return; - } - if (mCamera != null) { - Camera.Parameters parameters = mCamera.getParameters(); - if (parameters != null) { - int newState = cameraFlash; - switch (cameraFlash) { - case 0: //自动 - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); - newState = 1; - break; - case 1://open - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - newState = 2; - break; - case 2: //close - parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); - newState = 0; - break; - } - cameraFlash = newState; - CameraUtils.setCameraFlash(context, newState); - mCamera.setParameters(parameters); - } - } - } - - /** - * 拍照 - */ - public void takePhoto(Camera.PictureCallback callback) { - if (mCamera != null) { - try { - mCamera.takePicture(null, null, callback); - } catch (Exception e) { - Toast.makeText(context, "拍摄失败", Toast.LENGTH_SHORT).show(); - } - } - } - - - /** - * 开始录制视频 - */ - public void startMediaRecord(String savePath) { - if (mCamera == null || mProfile == null) return; - mCamera.unlock(); - if (mMediaRecorder == null) { - mMediaRecorder = new MediaRecorder(); - mMediaRecorder.setOrientationHint(90); - } - if (isCameraFrontFacing()) { - mMediaRecorder.setOrientationHint(270); - } - mMediaRecorder.reset(); - mMediaRecorder.setCamera(mCamera); - mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); - mMediaRecorder.setProfile(mProfile); - mMediaRecorder.setOutputFile(savePath); - try { - mMediaRecorder.prepare(); - mMediaRecorder.start(); - } catch (Exception e) { - e.printStackTrace(); - - } - } - - /** - * 停止录制 - */ - public void stopMediaRecord() { - this.cameraType = 0; - stopRecorder(); - releaseMediaRecorder(); - } - - private void releaseMediaRecorder() { - if (mMediaRecorder != null) { - try { - mMediaRecorder.reset(); - mMediaRecorder.release(); - mMediaRecorder = null; - mCamera.lock(); - } catch (Exception e) { - e.printStackTrace(); - LogUtils.i(e); - } - } - } - - private void stopRecorder() { - if (mMediaRecorder != null) { - try { - mMediaRecorder.stop(); - } catch (Exception e) { - e.printStackTrace(); - LogUtils.i(e); - } - - } - } - - public boolean isSupportFrontCamera() { - return isSupportFrontCamera; - } - - public boolean isSupportFlashCamera() { - return isSupportFlashCamera; - } - - public boolean isCameraFrontFacing() { - return cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT; - } - - /** - * 设置对焦类型 - * - * @param cameraType - */ - public void setCameraType(int cameraType) { - this.cameraType = cameraType; - if (mCamera != null) {//拍摄视频时 - if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { - Camera.Parameters parameters = mCamera.getParameters(); - List focusModes = parameters.getSupportedFocusModes(); - if (focusModes != null) { - if (cameraType == 0) { - if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { - parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); - } - } else { - if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - } - } - } - } - } - } - - public int getCameraFlash() { - return cameraFlash; - } - - /** - * 对焦 - * - * @param x - * @param y - */ - public void handleFocusMetering(float x, float y) { - Camera.Parameters params = mCamera.getParameters(); - Camera.Size previewSize = params.getPreviewSize(); - Rect focusRect = calculateTapArea(x, y, 1f, previewSize); - Rect meteringRect = calculateTapArea(x, y, 1.5f, previewSize); - mCamera.cancelAutoFocus(); - - if (params.getMaxNumFocusAreas() > 0) { - List focusAreas = new ArrayList<>(); - focusAreas.add(new Camera.Area(focusRect, 1000)); - params.setFocusAreas(focusAreas); - } else { - LogUtils.i("focus areas not supported"); - } - if (params.getMaxNumMeteringAreas() > 0) { - List meteringAreas = new ArrayList<>(); - meteringAreas.add(new Camera.Area(meteringRect, 1000)); - params.setMeteringAreas(meteringAreas); - } else { - LogUtils.i("metering areas not supported"); - } - final String currentFocusMode = params.getFocusMode(); - params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); - mCamera.setParameters(params); - - mCamera.autoFocus(new Camera.AutoFocusCallback() { - @Override - public void onAutoFocus(boolean success, Camera camera) { - Camera.Parameters params = camera.getParameters(); - params.setFocusMode(currentFocusMode); - camera.setParameters(params); - } - }); - } - - private Rect calculateTapArea(float x, float y, float coefficient, Camera.Size previewSize) { - float focusAreaSize = 300; - int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue(); - int centerX = (int) (x / previewSize.width - 1000); - int centerY = (int) (y / previewSize.height - 1000); - int left = clamp(centerX - areaSize / 2, -1000, 1000); - int top = clamp(centerY - areaSize / 2, -1000, 1000); - RectF rectF = new RectF(left, top, left + areaSize, top + areaSize); - return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom)); - } - - private int clamp(int x, int min, int max) { - if (x > max) { - return max; - } - if (x < min) { - return min; - } - return x; - } - -} +package jiguang.chat.utils.photovideo.takevideo.camera; + +import android.app.Application; +import android.content.Context; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.media.CamcorderProfile; +import android.media.MediaRecorder; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; + +import jiguang.chat.utils.photovideo.takevideo.utils.LogUtils; + + +/** + * 相机管理类 + */ + +public final class CameraManager { + + private Application context; + /** + * camera + */ + private Camera mCamera; + /** + * 视频录制 + */ + private MediaRecorder mMediaRecorder; + /** + * 相机闪光状态 + */ + private int cameraFlash; + /** + * 前后置状态 + */ + private int cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; + /** + * 是否支持前置摄像,是否支持闪光 + */ + private boolean isSupportFrontCamera, isSupportFlashCamera; + /** + * 录制视频的相关参数 + */ + private CamcorderProfile mProfile; + /** + * 0为拍照, 1为录像 + */ + private int cameraType; + + private CameraManager(Application context) { + this.context = context; + isSupportFrontCamera = CameraUtils.isSupportFrontCamera(); + isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context); + if (isSupportFrontCamera) { + cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK); + } + if (isSupportFlashCamera) { + cameraFlash = CameraUtils.getCameraFlash(context); + } + } + + private static CameraManager INSTANCE; + + public static CameraManager getInstance(Application context) { + if (INSTANCE == null) { + synchronized (CameraManager.class) { + if (INSTANCE == null) { + INSTANCE = new CameraManager(context); + } + } + } + return INSTANCE; + } + + /** + * 打开camera + */ + public void openCamera(Context context, SurfaceTexture surfaceTexture, int width, int height) { + if (mCamera == null) { + try { + mCamera = Camera.open(cameraFacing);//打开当前选中的摄像头 + mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH); + mCamera.setDisplayOrientation(90);//默认竖直拍照 + mCamera.setPreviewTexture(surfaceTexture); + initCameraParameters(cameraFacing, width, height); + mCamera.startPreview(); + } catch (Exception e) { + if (mCamera != null) { + mCamera.release(); + mCamera = null; + } + } + } + } + + + /** + * 开启预览,前提是camera初始化了 + */ + public void restartPreview() { + if (mCamera == null) return; + try { + Camera.Parameters parameters = mCamera.getParameters(); + int zoom = parameters.getZoom(); + if (zoom > 0) { + parameters.setZoom(0); + mCamera.setParameters(parameters); + } + mCamera.startPreview(); + } catch (Exception e) { + LogUtils.i(e); + if (mCamera != null) { + mCamera.release(); + mCamera = null; + } + } + } + + private void initCameraParameters(int cameraId, int width, int height) { + Camera.Parameters parameters = mCamera.getParameters(); + if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { + List focusModes = parameters.getSupportedFocusModes(); + if (focusModes != null) { + if (cameraType == 0) { + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } + } else { + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + } + } + } + parameters.setRotation(90);//设置旋转代码, + switch (cameraFlash) { + case 0: + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); + break; + case 1: + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + break; + case 2: + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + break; + } + List pictureSizes = parameters.getSupportedPictureSizes(); + List previewSizes = parameters.getSupportedPreviewSizes(); + if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) { + /*for (Camera.Size size : pictureSizes) { + LogUtils.i("pictureSize " + size.width + " " + size.height); + } + for (Camera.Size size : pictureSizes) { + LogUtils.i("previewSize " + size.width + " " + size.height); + }*/ + Camera.Size optimalPicSize = getOptimalSize(pictureSizes, width, height); + Camera.Size optimalPreSize = getOptimalSize(previewSizes, width, height); + LogUtils.i("TextureSize " + width + " " + height + " optimalSize pic " + optimalPicSize.width + " " + optimalPicSize.height + " pre " + optimalPreSize.width + " " + optimalPreSize.height); + parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height); + parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height); + mProfile.videoFrameWidth = optimalPreSize.width; + mProfile.videoFrameHeight = optimalPreSize.height; + mProfile.videoBitRate = 5000000;//此参数主要决定视频拍出大小 + } + mCamera.setParameters(parameters); + } + + /** + * 释放摄像头 + */ + public void closeCamera() { + this.cameraType = 0; + if (mCamera != null) { + try { + mCamera.stopPreview(); + mCamera.release(); + mCamera = null; + } catch (Exception e) { + LogUtils.i(e); + if (mCamera != null) { + mCamera.release(); + mCamera = null; + } + } + } + } + + /** + * 集合不为空 + * + * @param list + * @param + * @return + */ + private boolean isEmpty(List list) { + return list == null || list.isEmpty(); + } + + /** + * 获取最佳预览相机Size参数 + * + * @return + */ + private Camera.Size getOptimalSize(List sizes, int w, int h) { + Camera.Size optimalSize = null; + float targetRadio = h / (float) w; + float optimalDif = Float.MAX_VALUE; //最匹配的比例 + int optimalMaxDif = Integer.MAX_VALUE;//最优的最大值差距 + for (Camera.Size size : sizes) { + float newOptimal = size.width / (float) size.height; + float newDiff = Math.abs(newOptimal - targetRadio); + if (newDiff < optimalDif) { //更好的尺寸 + optimalDif = newDiff; + optimalSize = size; + optimalMaxDif = Math.abs(h - size.width); + } else if (newDiff == optimalDif) {//更好的尺寸 + int newOptimalMaxDif = Math.abs(h - size.width); + if (newOptimalMaxDif < optimalMaxDif) { + optimalDif = newDiff; + optimalSize = size; + optimalMaxDif = newOptimalMaxDif; + } + } + } + return optimalSize; + } + + /** + * 缩放 + * + * @param isZoomIn + */ + public void handleZoom(boolean isZoomIn) { + if (mCamera == null) return; + Camera.Parameters params = mCamera.getParameters(); + if (params == null) return; + if (params.isZoomSupported()) { + int maxZoom = params.getMaxZoom(); + int zoom = params.getZoom(); + if (isZoomIn && zoom < maxZoom) { + zoom++; + } else if (zoom > 0) { + zoom--; + } + params.setZoom(zoom); + mCamera.setParameters(params); + } else { + LogUtils.i("zoom not supported"); + } + } + + /** + * 更换前后置摄像 + */ + public void changeCameraFacing(Context context, SurfaceTexture surfaceTexture, int width, int height) { + if (isSupportFrontCamera) { + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 + for (int i = 0; i < cameraCount; i++) { + Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息 + if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //现在是后置,变更为前置 + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位为前置 + closeCamera(); + cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; + CameraUtils.setCameraFacing(context, cameraFacing); + openCamera(context, surfaceTexture, width, height); + break; + } + } else {//现在是前置, 变更为后置 + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位 + closeCamera(); + cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT; + CameraUtils.setCameraFacing(context, cameraFacing); + openCamera(context, surfaceTexture, width, height); + break; + } + } + } + } else { //不支持摄像机 + Toast.makeText(context, "您的手机不支持前置摄像", Toast.LENGTH_SHORT).show(); + } + } + + /** + * 改变闪光状态 + */ + public void changeCameraFlash(SurfaceTexture surfaceTexture, int width, int height) { + if (!isSupportFlashCamera) { + Toast.makeText(context, "您的手机不支闪光", Toast.LENGTH_SHORT).show(); + return; + } + if (mCamera != null) { + Camera.Parameters parameters = mCamera.getParameters(); + if (parameters != null) { + int newState = cameraFlash; + switch (cameraFlash) { + case 0: //自动 + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); + newState = 1; + break; + case 1://open + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + newState = 2; + break; + case 2: //close + parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO); + newState = 0; + break; + } + cameraFlash = newState; + CameraUtils.setCameraFlash(context, newState); + mCamera.setParameters(parameters); + } + } + } + + /** + * 拍照 + */ + public void takePhoto(Camera.PictureCallback callback) { + if (mCamera != null) { + try { + mCamera.takePicture(null, null, callback); + } catch (Exception e) { + Toast.makeText(context, "拍摄失败", Toast.LENGTH_SHORT).show(); + } + } + } + + + /** + * 开始录制视频 + */ + public void startMediaRecord(String savePath) { + if (mCamera == null || mProfile == null) return; + mCamera.unlock(); + if (mMediaRecorder == null) { + mMediaRecorder = new MediaRecorder(); + mMediaRecorder.setOrientationHint(90); + } + if (isCameraFrontFacing()) { + mMediaRecorder.setOrientationHint(270); + } + mMediaRecorder.reset(); + mMediaRecorder.setCamera(mCamera); + mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); + mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); + mMediaRecorder.setProfile(mProfile); + mMediaRecorder.setOutputFile(savePath); + try { + mMediaRecorder.prepare(); + mMediaRecorder.start(); + } catch (Exception e) { + e.printStackTrace(); + + } + } + + /** + * 停止录制 + */ + public void stopMediaRecord() { + this.cameraType = 0; + stopRecorder(); + releaseMediaRecorder(); + } + + private void releaseMediaRecorder() { + if (mMediaRecorder != null) { + try { + mMediaRecorder.reset(); + mMediaRecorder.release(); + mMediaRecorder = null; + mCamera.lock(); + } catch (Exception e) { + e.printStackTrace(); + LogUtils.i(e); + } + } + } + + private void stopRecorder() { + if (mMediaRecorder != null) { + try { + mMediaRecorder.stop(); + } catch (Exception e) { + e.printStackTrace(); + LogUtils.i(e); + } + + } + } + + public boolean isSupportFrontCamera() { + return isSupportFrontCamera; + } + + public boolean isSupportFlashCamera() { + return isSupportFlashCamera; + } + + public boolean isCameraFrontFacing() { + return cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT; + } + + /** + * 设置对焦类型 + * + * @param cameraType + */ + public void setCameraType(int cameraType) { + this.cameraType = cameraType; + if (mCamera != null) {//拍摄视频时 + if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { + Camera.Parameters parameters = mCamera.getParameters(); + List focusModes = parameters.getSupportedFocusModes(); + if (focusModes != null) { + if (cameraType == 0) { + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } + } else { + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + } + } + } + } + } + + public int getCameraFlash() { + return cameraFlash; + } + + /** + * 对焦 + * + * @param x + * @param y + */ + public void handleFocusMetering(float x, float y) { + if (mCamera == null) { // TODO:2019/05/22 使用三星手机发送小视频时会报空指针异常,这里先判断非空,后续查找原因 + return; + } + Camera.Parameters params = mCamera.getParameters(); + Camera.Size previewSize = params.getPreviewSize(); + Rect focusRect = calculateTapArea(x, y, 1f, previewSize); + Rect meteringRect = calculateTapArea(x, y, 1.5f, previewSize); + mCamera.cancelAutoFocus(); + + if (params.getMaxNumFocusAreas() > 0) { + List focusAreas = new ArrayList<>(); + focusAreas.add(new Camera.Area(focusRect, 1000)); + params.setFocusAreas(focusAreas); + } else { + LogUtils.i("focus areas not supported"); + } + if (params.getMaxNumMeteringAreas() > 0) { + List meteringAreas = new ArrayList<>(); + meteringAreas.add(new Camera.Area(meteringRect, 1000)); + params.setMeteringAreas(meteringAreas); + } else { + LogUtils.i("metering areas not supported"); + } + final String currentFocusMode = params.getFocusMode(); + params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); + mCamera.setParameters(params); + + mCamera.autoFocus(new Camera.AutoFocusCallback() { + @Override + public void onAutoFocus(boolean success, Camera camera) { + Camera.Parameters params = camera.getParameters(); + params.setFocusMode(currentFocusMode); + camera.setParameters(params); + } + }); + } + + private Rect calculateTapArea(float x, float y, float coefficient, Camera.Size previewSize) { + float focusAreaSize = 300; + int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue(); + int centerX = (int) (x / previewSize.width - 1000); + int centerY = (int) (y / previewSize.height - 1000); + int left = clamp(centerX - areaSize / 2, -1000, 1000); + int top = clamp(centerY - areaSize / 2, -1000, 1000); + RectF rectF = new RectF(left, top, left + areaSize, top + areaSize); + return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom)); + } + + private int clamp(int x, int min, int max) { + if (x > max) { + return max; + } + if (x < min) { + return min; + } + return x; + } + +} diff --git a/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/utils/FileUtils.java b/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/utils/FileUtils.java index cece39af..62db9ca7 100755 --- a/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/utils/FileUtils.java +++ b/chatapp/src/main/java/jiguang/chat/utils/photovideo/takevideo/utils/FileUtils.java @@ -8,6 +8,7 @@ import android.os.Environment; import android.os.StatFs; import android.text.TextUtils; +import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -22,6 +23,7 @@ public class FileUtils { + private static final String TAG = FileUtils.class.getSimpleName(); /** * 随机命名 */ @@ -143,13 +145,17 @@ public static String getUploadVideoFile(Context context) { */ public static boolean savePhoto(String photoPath, byte[] data, boolean isFrontFacing) { if (photoPath != null && data != null) { + int degree = getOrientation(data); FileOutputStream fos = null; try { Bitmap preBitmap = compressBitmap(data, MAX_WIDTH, MAX_HEIGHT); + Matrix matrix = new Matrix(); + matrix.postRotate(degree); if (isFrontFacing) { - Matrix matrix = new Matrix(); matrix.postScale(1, -1); - Bitmap newBitmap = Bitmap.createBitmap(preBitmap, 0, 0, preBitmap.getWidth(), preBitmap.getHeight(), matrix, true); + } + Bitmap newBitmap = Bitmap.createBitmap(preBitmap, 0, 0, preBitmap.getWidth(), preBitmap.getHeight(), matrix, true); + if (preBitmap != newBitmap) { preBitmap.recycle(); preBitmap = newBitmap; } @@ -360,4 +366,117 @@ public static boolean writeFile(String str, File file, boolean append) { return false; } + public static int getOrientation(byte[] jpeg) { + if (jpeg == null) { + return 0; + } + + int offset = 0; + int length = 0; + + // ISO/IEC 10918-1:1993(E) + while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) { + int marker = jpeg[offset] & 0xFF; + + // Check if the marker is a padding. + if (marker == 0xFF) { + continue; + } + offset++; + + // Check if the marker is SOI or TEM. + if (marker == 0xD8 || marker == 0x01) { + continue; + } + // Check if the marker is EOI or SOS. + if (marker == 0xD9 || marker == 0xDA) { + break; + } + + // Get the length and check if it is reasonable. + length = pack(jpeg, offset, 2, false); + if (length < 2 || offset + length > jpeg.length) { + Log.e("69523", "Invalid length"); + return 0; + } + + // Break if the marker is EXIF in APP1. + if (marker == 0xE1 && length >= 8 && + pack(jpeg, offset + 2, 4, false) == 0x45786966 && + pack(jpeg, offset + 6, 2, false) == 0) { + offset += 8; + length -= 8; + break; + } + + // Skip other markers. + offset += length; + length = 0; + } + + // JEITA CP-3451 Exif Version 2.2 + if (length > 8) { + // Identify the byte order. + int tag = pack(jpeg, offset, 4, false); + if (tag != 0x49492A00 && tag != 0x4D4D002A) { + Log.e("69523", "Invalid byte order"); + return 0; + } + boolean littleEndian = (tag == 0x49492A00); + + // Get the offset and check if it is reasonable. + int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; + if (count < 10 || count > length) { + Log.e(TAG, "Invalid offset"); + return 0; + } + offset += count; + length -= count; + + // Get the count and go through all the elements. + count = pack(jpeg, offset - 2, 2, littleEndian); + while (count-- > 0 && length >= 12) { + // Get the tag and check if it is orientation. + tag = pack(jpeg, offset, 2, littleEndian); + if (tag == 0x0112) { + // We do not really care about type and count, do we? + int orientation = pack(jpeg, offset + 8, 2, littleEndian); + switch (orientation) { + case 1: + return 0; + case 3: + return 180; + case 6: + return 90; + case 8: + return 270; + } + Log.i(TAG, "Unsupported orientation"); + return 0; + } + offset += 12; + length -= 12; + } + } + + Log.i(TAG, "Orientation not found"); + return 0; + } + + private static int pack(byte[] bytes, int offset, int length, + boolean littleEndian) { + int step = 1; + if (littleEndian) { + offset += length - 1; + step = -1; + } + + int value = 0; + while (length-- > 0) { + value = (value << 8) | (bytes[offset] & 0xFF); + offset += step; + } + return value; + } + } diff --git a/chatapp/src/main/java/jiguang/chat/view/ChatDetailView.java b/chatapp/src/main/java/jiguang/chat/view/ChatDetailView.java index 26beed58..811995ce 100644 --- a/chatapp/src/main/java/jiguang/chat/view/ChatDetailView.java +++ b/chatapp/src/main/java/jiguang/chat/view/ChatDetailView.java @@ -25,8 +25,6 @@ public class ChatDetailView extends LinearLayout { private LinearLayout mGroupDescLL; - private View mSplitLine1; - private View mSplitLine2; private LinearLayout mGroupNameLL; private LinearLayout mMyNameLL; private LinearLayout mGroupNumLL; @@ -52,6 +50,11 @@ public class ChatDetailView extends LinearLayout { private LinearLayout mDetailAddFriend; private RelativeLayout mClear_rl; private ImageView mIv_groupAvatar; + private TextView mMoreGroupMember; + private TextView mTv_memberCount; + private TextView mTv_groupType; + private TextView mTv_groupID; + private LinearLayout mChat_silence; public ChatDetailView(Context context, AttributeSet attrs) { super(context, attrs); @@ -62,8 +65,6 @@ public ChatDetailView(Context context, AttributeSet attrs) { public void initModule() { mGroupDescLL = (LinearLayout) findViewById(R.id.group_desc_ll); mGroupDesc = (TextView) findViewById(R.id.chat_detail_group_desc); - mSplitLine1 = findViewById(R.id.all_member_split_line1); - mSplitLine2 = findViewById(R.id.all_member_split_line2); mGroupNameLL = (LinearLayout) findViewById(R.id.group_name_ll); mGroupAvatarLL = (RelativeLayout) findViewById(R.id.rl_groupAvatar); mIv_groupAvatar = (ImageView) findViewById(R.id.iv_groupAvatar); @@ -72,6 +73,7 @@ public void initModule() { mGroupChatRecordLL = (LinearLayout) findViewById(R.id.group_chat_record_ll); mGroupChatDelLL = (LinearLayout) findViewById(R.id.group_chat_del_ll); mChatFile = (LinearLayout) findViewById(R.id.chat_file); + mChat_silence = findViewById(R.id.chat_silence); mReturnBtn = (ImageButton) findViewById(R.id.return_btn); mTitle = (TextView) findViewById(R.id.title); mMenuBtn = (ImageButton) findViewById(R.id.right_btn); @@ -84,6 +86,10 @@ public void initModule() { mBlockBtn = (SlipButton) findViewById(R.id.block_slip_btn); mBlockLine = findViewById(R.id.block_split_line); mTv_moreGroup = (LinearLayout) findViewById(R.id.tv_moreGroup); + mTv_memberCount = findViewById(R.id.tv_memberCount); + mMoreGroupMember = findViewById(R.id.moreGroupMember); + mTv_groupType = findViewById(R.id.tv_groupType); + mTv_groupID = findViewById(R.id.tv_groupID); mAddFriend = (Button) findViewById(R.id.chat_detail_add_friend); mDetailAddFriend = (LinearLayout) findViewById(R.id.detail_add_friend); mClear_rl = (RelativeLayout) findViewById(R.id.clear_rl); @@ -106,9 +112,12 @@ public void setListeners(OnClickListener onClickListener) { mReturnBtn.setOnClickListener(onClickListener); mDelGroupBtn.setOnClickListener(onClickListener); mTv_moreGroup.setOnClickListener(onClickListener); + mMoreGroupMember.setOnClickListener(onClickListener); mAddFriend.setOnClickListener(onClickListener); mClear_rl.setOnClickListener(onClickListener); mChatFile.setOnClickListener(onClickListener); + mChat_silence.setOnClickListener(onClickListener); + } public void setOnChangeListener(SlipButton.OnChangedListener listener) { @@ -120,6 +129,18 @@ public void setItemListener(AdapterView.OnItemClickListener listener) { mGridView.setOnItemClickListener(listener); } + public void setGroupType(String type) { + mTv_groupType.setText(type); + } + + public void setGroupId(String groupId) { + mTv_groupID.setText(groupId); + } + + public void setMemberCount(String count) { + mTv_memberCount.setText(count); + } + public void setTitle(String title) { mTitle.setText(title); } @@ -144,10 +165,19 @@ public void setSingleView(boolean friend) { mDetailAddFriend.setVisibility(VISIBLE); mDelGroupBtn.setVisibility(GONE); } + mGroupDescLL.setVisibility(View.GONE); mGroupNameLL.setVisibility(View.GONE); mGroupAvatarLL.setVisibility(View.GONE); mGroupNumLL.setVisibility(View.GONE); mMyNameLL.setVisibility(View.GONE); + findViewById(R.id.group_id).setVisibility(View.GONE); + findViewById(R.id.group_type).setVisibility(View.GONE); + findViewById(R.id.chat_silence).setVisibility(View.GONE); + findViewById(R.id.single_chat_remove_1).setVisibility(View.GONE); + findViewById(R.id.single_chat_remove_2).setVisibility(View.GONE); + findViewById(R.id.single_chat_remove_3).setVisibility(View.GONE); + findViewById(R.id.single_chat_remove_4).setVisibility(View.GONE); + findViewById(R.id.single_chat_remove_5).setVisibility(View.GONE); mDelGroupBtn.setText("删除好友"); } @@ -164,12 +194,6 @@ public void setGroupDesc(String desc) { mGroupDesc.setText(desc); } - public void dismissAllMembersBtn() { - mSplitLine1.setVisibility(View.GONE); - mSplitLine2.setVisibility(View.GONE); - mGroupDescLL.setVisibility(View.GONE); - } - public void initNoDisturb(int status) { mNoDisturbBtn.setChecked(status == 1); } diff --git a/chatapp/src/main/java/jiguang/chat/view/ChatRoomView.java b/chatapp/src/main/java/jiguang/chat/view/ChatRoomView.java new file mode 100644 index 00000000..9d96e117 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/view/ChatRoomView.java @@ -0,0 +1,79 @@ +package jiguang.chat.view; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.scwang.smartrefresh.layout.SmartRefreshLayout; +import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener; +import com.scwang.smartrefresh.layout.listener.OnRefreshListener; + +import jiguang.chat.R; +import jiguang.chat.adapter.ChatRoomAdapter; +import jiguang.chat.controller.ChatRoomController; + +/** + * Created by ${chenyn} on 2017/10/31. + */ + +public class ChatRoomView extends LinearLayout { + private ChatRoomController mListener; + private Context mContext; + private ListView mChatRoomListView; + private LayoutInflater mInflater; + private LinearLayout mSearch_title; + private SmartRefreshLayout smartRefreshLayout; + private TextView mNullChatRoom; + + public ChatRoomView(Context context) { + super(context); + } + + public ChatRoomView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + this.mContext = context; + mInflater = LayoutInflater.from(context); + } + + + public void initModule() { + View view = LayoutInflater.from(mContext).inflate(R.layout.item_search, null); + TextView titleText = view.findViewById(R.id.tv_chatRoomTitle); + titleText.setText("聊天室ID"); + mSearch_title = view.findViewById(R.id.search_title); + mChatRoomListView = findViewById(R.id.lv_chatRoom); + mChatRoomListView.addHeaderView(view); + smartRefreshLayout = findViewById(R.id.refreshLayout); + mNullChatRoom = findViewById(R.id.null_chatRoom); + } + + public void setListener(ChatRoomController listener) { + mChatRoomListView.setOnItemClickListener(listener); + } + + public void setClickListener(ChatRoomController listener) { + mSearch_title.setOnClickListener(listener); + } + + public void setChatRoomAdapter(ChatRoomAdapter chatRoomAdapter) { + mChatRoomListView.setAdapter(chatRoomAdapter); + } + + public void setOnRefreshListener(OnRefreshListener onRefreshListener) { + smartRefreshLayout.setOnRefreshListener(onRefreshListener); + } + + public void setOnLoadMoreListener(OnLoadMoreListener loadMoreListener) { + smartRefreshLayout.setOnLoadMoreListener(loadMoreListener); + } + + public void setNullChatRoom(boolean isNullChatRoom) { + mNullChatRoom.setVisibility(isNullChatRoom ? VISIBLE : GONE); + } + +} diff --git a/chatapp/src/main/java/jiguang/chat/view/ChatView.java b/chatapp/src/main/java/jiguang/chat/view/ChatView.java index 52151178..160b111d 100644 --- a/chatapp/src/main/java/jiguang/chat/view/ChatView.java +++ b/chatapp/src/main/java/jiguang/chat/view/ChatView.java @@ -50,16 +50,20 @@ public void initModule(float density, int densityDpi) { mChatTitle = (TextView) findViewById(R.id.jmui_title); mAtMeBtn = (Button) findViewById(R.id.jmui_at_me_btn); if (densityDpi <= 160) { - mChatTitle.setMaxWidth((int)(180 * density + 0.5f)); - }else if (densityDpi <= 240) { - mChatTitle.setMaxWidth((int)(190 * density + 0.5f)); - }else { - mChatTitle.setMaxWidth((int)(200 * density + 0.5f)); + mChatTitle.setMaxWidth((int) (180 * density + 0.5f)); + } else if (densityDpi <= 240) { + mChatTitle.setMaxWidth((int) (190 * density + 0.5f)); + } else { + mChatTitle.setMaxWidth((int) (200 * density + 0.5f)); } mChatListView = (DropDownListView) findViewById(R.id.lv_chat); } + public DropDownListView getChatListView() { + return mChatListView; + } + public void setToPosition(int position) { mChatListView.smoothScrollToPosition(position); mAtMeBtn.setVisibility(GONE); @@ -72,6 +76,7 @@ public void setChatListAdapter(ChattingListAdapter chatAdapter) { public DropDownListView getListView() { return mChatListView; } + public void setToBottom() { mChatListView.clearFocus(); mChatListView.post(new Runnable() { @@ -81,6 +86,7 @@ public void run() { } }); } + public void setConversation(Conversation conv) { this.mConv = conv; } @@ -112,6 +118,7 @@ public void setChatTitle(int id, int count) { public void setChatTitle(int id) { mChatTitle.setText(id); } + public void showAtMeButton() { mAtMeBtn.setVisibility(VISIBLE); } @@ -127,6 +134,11 @@ public void setChatTitle(String name, int count) { public void setChatTitle(String title) { mChatTitle.setText(title); } + + public void setTitle(String title) { + mChatTitle.setText(title); + } + public void dismissGroupNum() { mGroupNumTv.setVisibility(View.GONE); } diff --git a/chatapp/src/main/java/jiguang/chat/view/ContactsView.java b/chatapp/src/main/java/jiguang/chat/view/ContactsView.java index a4b9d22c..1679a7fe 100644 --- a/chatapp/src/main/java/jiguang/chat/view/ContactsView.java +++ b/chatapp/src/main/java/jiguang/chat/view/ContactsView.java @@ -18,7 +18,7 @@ import jiguang.chat.controller.ContactsController; import jiguang.chat.utils.SharePreferenceManager; import jiguang.chat.utils.sidebar.SideBar; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; /** @@ -75,13 +75,16 @@ public void initModule(float ratio, float density) { RelativeLayout loadingHeader = (RelativeLayout) mInflater.inflate(R.layout.jmui_drop_down_list_header, null); mLoadingIv = (ImageView) loadingHeader.findViewById(R.id.jmui_loading_img); mLoadingTv = (LinearLayout) loadingHeader.findViewById(R.id.loading_view); - mNewFriendNum.setVisibility(INVISIBLE); mListView.addHeaderView(loadingHeader); mListView.addHeaderView(header, null, false); mListView.setDrawingListUnderStickyHeader(true); mListView.setAreHeadersSticky(true); mListView.setStickyHeaderTopOffset(0); - + if (SharePreferenceManager.getCachedNewFriendNum() > 0) { + showNewFriends(SharePreferenceManager.getCachedNewFriendNum()); + } else { + mNewFriendNum.setVisibility(INVISIBLE); + } } @@ -115,6 +118,7 @@ public void showNewFriends(int num) { public void dismissNewFriends() { SharePreferenceManager.setCachedNewFriendNum(0); + JGApplication.forAddIntoGroup.clear(); JGApplication.forAddFriend.clear(); mNewFriendNum.setVisibility(INVISIBLE); } diff --git a/chatapp/src/main/java/jiguang/chat/view/MainView.java b/chatapp/src/main/java/jiguang/chat/view/MainView.java index 94e52ab3..97ac9bb1 100644 --- a/chatapp/src/main/java/jiguang/chat/view/MainView.java +++ b/chatapp/src/main/java/jiguang/chat/view/MainView.java @@ -6,8 +6,10 @@ import android.util.AttributeSet; import android.widget.Button; import android.widget.RelativeLayout; +import android.widget.TextView; import jiguang.chat.R; +import jiguang.chat.utils.SharePreferenceManager; /** * Created by ${chenyn} on 2017/2/20. @@ -18,23 +20,31 @@ public class MainView extends RelativeLayout { private Button[] mBtnList; private int[] mBtnListID; private ScrollControlViewPager mViewContainer; + private TextView mAllContactNumber; public MainView(Context context, AttributeSet attrs) { super(context, attrs); } - public void initModule() { mBtnListID = new int[] { - R.id.actionbar_msg_btn, R.id.actionbar_contact_btn, R.id.actionbar_me_btn - }; - mBtnList = new Button[3]; - for (int i = 0; i < 3; i++) { + R.id.actionbar_msg_btn, R.id.actionbar_chatroom_btn, + R.id.actionbar_contact_btn, R.id.actionbar_me_btn}; + mBtnList = new Button[mBtnListID.length]; + for (int i = 0; i < mBtnListID.length; i++) { mBtnList[i] = (Button) findViewById(mBtnListID[i]); } mViewContainer = (ScrollControlViewPager) findViewById(R.id.viewpager); + mViewContainer.setOffscreenPageLimit(2); mBtnList[0].setTextColor(getResources().getColor(R.color.actionbar_pres_color)); mBtnList[0].setSelected(true); + mAllContactNumber = findViewById(R.id.all_contact_number); + if (SharePreferenceManager.getCachedNewFriendNum() > 0) { + mAllContactNumber.setVisibility(VISIBLE); + mAllContactNumber.setText(String.valueOf(SharePreferenceManager.getCachedNewFriendNum())); + } else { + mAllContactNumber.setVisibility(GONE); + } } public void setOnClickListener(OnClickListener onclickListener) { @@ -56,7 +66,7 @@ public void setCurrentItem(int index, boolean scroll) { } public void setButtonColor(int index) { - for (int i = 0; i < 3; i++) { + for (int i = 0; i < mBtnListID.length; i++) { if (index == i) { mBtnList[i].setSelected(true); mBtnList[i].setTextColor(getResources().getColor(R.color.actionbar_pres_color)); diff --git a/chatapp/src/main/java/jiguang/chat/view/MenuItemView.java b/chatapp/src/main/java/jiguang/chat/view/MenuItemView.java index 0407bfce..912811f9 100644 --- a/chatapp/src/main/java/jiguang/chat/view/MenuItemView.java +++ b/chatapp/src/main/java/jiguang/chat/view/MenuItemView.java @@ -1,7 +1,7 @@ package jiguang.chat.view; import android.view.View; -import android.widget.LinearLayout; +import android.widget.RelativeLayout; import jiguang.chat.R; @@ -9,20 +9,22 @@ public class MenuItemView { private View mView; - private LinearLayout mCreateGroupLl; - private LinearLayout mAddFriendLl; - private LinearLayout mSendMsgLl; - private LinearLayout mLl_saoYiSao; + private RelativeLayout mCreateGroupLl; + private RelativeLayout mAddFriendLl; + private RelativeLayout mSendMsgLl; + private RelativeLayout mLl_saoYiSao; + private RelativeLayout mAdd_open_group; public MenuItemView(View view) { this.mView = view; } public void initModule() { - mCreateGroupLl = (LinearLayout) mView.findViewById(R.id.create_group_ll); - mAddFriendLl = (LinearLayout) mView.findViewById(R.id.add_friend_with_confirm_ll); - mSendMsgLl = (LinearLayout) mView.findViewById(R.id.send_message_ll); - mLl_saoYiSao = (LinearLayout) mView.findViewById(R.id.ll_saoYiSao); + mCreateGroupLl = mView.findViewById(R.id.create_group_ll); + mAddFriendLl = mView.findViewById(R.id.add_friend_with_confirm_ll); + mSendMsgLl = mView.findViewById(R.id.send_message_ll); + mLl_saoYiSao = mView.findViewById(R.id.ll_saoYiSao); + mAdd_open_group = mView.findViewById(R.id.add_open_group); } public void setListeners(View.OnClickListener listener) { @@ -30,6 +32,7 @@ public void setListeners(View.OnClickListener listener) { mAddFriendLl.setOnClickListener(listener); mSendMsgLl.setOnClickListener(listener); mLl_saoYiSao.setOnClickListener(listener); + mAdd_open_group.setOnClickListener(listener); } public void showAddFriendDirect() { diff --git a/chatapp/src/main/java/jiguang/chat/view/NoScrollGridView.java b/chatapp/src/main/java/jiguang/chat/view/NoScrollGridView.java new file mode 100644 index 00000000..745f8f8e --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/view/NoScrollGridView.java @@ -0,0 +1,48 @@ +package jiguang.chat.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +public class NoScrollGridView extends GridView { + private int mRequestedNumColumns = 0; + + public NoScrollGridView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoScrollGridView(Context context) { + super(context); + } + + public NoScrollGridView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void setNumColumns(int numColumns) { + super.setNumColumns(numColumns); + if (numColumns != mRequestedNumColumns) { + mRequestedNumColumns = numColumns; + } + } + + /** + * 设置gridView不可滑动,并且设置gridView宽度 + * @param widthMeasureSpec + * @param heightMeasureSpec + */ + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec( + Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + if (mRequestedNumColumns > 0) { + int width = (mRequestedNumColumns * getColumnWidth()) + + ((mRequestedNumColumns-1) * getHorizontalSpacing()) + + getListPaddingLeft() + getListPaddingRight(); + + setMeasuredDimension(width, getMeasuredHeight()); + } + } +} diff --git a/chatapp/src/main/java/jiguang/chat/view/NoScrollViewPager.java b/chatapp/src/main/java/jiguang/chat/view/NoScrollViewPager.java new file mode 100644 index 00000000..97b0695b --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/view/NoScrollViewPager.java @@ -0,0 +1,35 @@ +package jiguang.chat.view; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * Created by ${chenyn} on 2017/10/22. + */ + +public class NoScrollViewPager extends ViewPager { + public NoScrollViewPager(Context context) { + super(context); + } + + public NoScrollViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return super.dispatchTouchEvent(ev); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return true; + } +} diff --git a/chatapp/src/main/java/jiguang/chat/view/RecordVoiceButton.java b/chatapp/src/main/java/jiguang/chat/view/RecordVoiceButton.java index 9805f4a3..23a54ee8 100644 --- a/chatapp/src/main/java/jiguang/chat/view/RecordVoiceButton.java +++ b/chatapp/src/main/java/jiguang/chat/view/RecordVoiceButton.java @@ -36,6 +36,7 @@ import cn.jpush.im.android.api.model.Message; import cn.jpush.im.android.api.model.UserInfo; import cn.jpush.im.android.api.options.MessageSendingOptions; +import cn.jpush.im.api.BasicCallback; import jiguang.chat.R; import jiguang.chat.adapter.ChattingListAdapter; import jiguang.chat.utils.FileHelper; @@ -80,6 +81,7 @@ public class RecordVoiceButton extends Button { private Chronometer mVoiceTime; private TextView mTimeDown; private LinearLayout mMicShow; + private String mUserName; public RecordVoiceButton(Context context) { super(context); @@ -111,6 +113,10 @@ public void initConv(Conversation conv, ChattingListAdapter adapter, ChatView ch this.mMsgListAdapter = adapter; mChatView = chatView; + if (conv.getType() == ConversationType.single) { + UserInfo userInfo = (UserInfo) conv.getTargetInfo(); + mUserName = userInfo.getUserName(); + } } @Override @@ -121,6 +127,14 @@ public boolean onTouchEvent(MotionEvent event) { mTimeShort.setContentView(R.layout.send_voice_time_short); switch (action) { case MotionEvent.ACTION_DOWN: + if (mConv.getType() == ConversationType.single) { + JMessageClient.sendSingleTransCommand(mUserName, null, "对方正在说话...", new BasicCallback() { + @Override + public void gotResult(int i, String s) { + + } + }); + } //文字 松开结束 this.setText(mContext.getString(R.string.jmui_send_voice_hint)); mIsPressed = true; @@ -149,6 +163,14 @@ public void run() { } break; case MotionEvent.ACTION_UP: + if (mConv.getType() == ConversationType.single) { + JMessageClient.sendSingleTransCommand(mUserName, null, mConv.getTitle(), new BasicCallback() { + @Override + public void gotResult(int i, String s) { + + } + }); + } //文字 按住说话 this.setText(mContext.getString(R.string.jmui_record_voice_hint)); mIsPressed = false; @@ -515,7 +537,7 @@ public void handleMessage(android.os.Message msg) { // .getString(controller.mContext, "jmui_rest_record_time_hint")), restTime)); controller.mMicShow.setVisibility(GONE); controller.mTimeDown.setVisibility(VISIBLE); - controller.mTimeDown.setText(restTime+""); + controller.mTimeDown.setText(restTime + ""); // 倒计时结束,发送语音, 重置状态 } else if (restTime == 0) { diff --git a/chatapp/src/main/java/jiguang/chat/view/SelectFriendView.java b/chatapp/src/main/java/jiguang/chat/view/SelectFriendView.java index c0f56cb2..21331812 100644 --- a/chatapp/src/main/java/jiguang/chat/view/SelectFriendView.java +++ b/chatapp/src/main/java/jiguang/chat/view/SelectFriendView.java @@ -11,7 +11,7 @@ import jiguang.chat.R; import jiguang.chat.adapter.StickyListAdapter; import jiguang.chat.utils.sidebar.SideBar; -import jiguang.chat.view.listview.StickyListHeadersListView; +import se.emilsjolander.stickylistheaders.StickyListHeadersListView; public class SelectFriendView extends LinearLayout { diff --git a/chatapp/src/main/java/jiguang/chat/view/listview/AdapterWrapper.java b/chatapp/src/main/java/jiguang/chat/view/listview/AdapterWrapper.java index 84f60466..092bf047 100644 --- a/chatapp/src/main/java/jiguang/chat/view/listview/AdapterWrapper.java +++ b/chatapp/src/main/java/jiguang/chat/view/listview/AdapterWrapper.java @@ -12,8 +12,9 @@ import java.util.LinkedList; import java.util.List; + import jiguang.chat.view.CheckableWrapperView; -import jiguang.chat.adapter.StickyListHeadersAdapter; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; /** diff --git a/chatapp/src/main/java/jiguang/chat/view/listview/LoadMoreListView.java b/chatapp/src/main/java/jiguang/chat/view/listview/LoadMoreListView.java new file mode 100644 index 00000000..22781384 --- /dev/null +++ b/chatapp/src/main/java/jiguang/chat/view/listview/LoadMoreListView.java @@ -0,0 +1,114 @@ +package jiguang.chat.view.listview; + +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AbsListView; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.RelativeLayout; + +import jiguang.chat.R; + +public class LoadMoreListView extends ListView implements AbsListView.OnScrollListener { + + //是否加载中或已加载所有数据 + private boolean mIsLoadingOrComplete; + //是否所有条目都可见 + private boolean mIsAllVisible; + + private OnLoadMoreListener mOnLoadMoreListener; + private RelativeLayout loadLayout; + private View mLoadCompleteView; + + public LoadMoreListView(Context context) { + super(context); + init(context); + } + + public LoadMoreListView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public LoadMoreListView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + //加载更多回调接口 + public interface OnLoadMoreListener { + void loadMore(); + } + + //初始化 + private void init(Context context) { + loadLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.jmui_drop_down_list_header, null); + mLoadCompleteView = LayoutInflater.from(context).inflate(R.layout.load_complete, null); +// mLoadCompleteView.setOnClickListener(); + setOnScrollListener(this); + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + //(最后一条可见item==最后一条item)&&(停止滑动)&&(!加载数据中)&&(!所有条目都可见) + if (view.getLastVisiblePosition() == getAdapter().getCount() - 1 && scrollState == SCROLL_STATE_IDLE && !mIsLoadingOrComplete && !mIsAllVisible) { + if (null != mOnLoadMoreListener) { + //加载更多 + mIsLoadingOrComplete = true; + mOnLoadMoreListener.loadMore(); + } + } + if (getFooterViewsCount() == 0 && !mIsAllVisible) { + loadLayout.findViewById(R.id.loading_view).setVisibility(VISIBLE); + ImageView loading = loadLayout.findViewById(R.id.jmui_loading_img); + AnimationDrawable drawable = (AnimationDrawable) loading.getDrawable(); + drawable.start(); + addFooterView(loadLayout); + } + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + mIsAllVisible = totalItemCount == visibleItemCount; + if (mIsAllVisible && !mIsLoadingOrComplete && totalItemCount > ((ListView) view).getFooterViewsCount() + ((ListView) view).getHeaderViewsCount()) { + if (null != mOnLoadMoreListener) { + mIsLoadingOrComplete = true; + mOnLoadMoreListener.loadMore(); + } + } + } + + /** + * 加载更多回调 + * + * @param onLoadMoreListener 加载更多回调接口 + */ + public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) { + mOnLoadMoreListener = onLoadMoreListener; + } + + /** + * 通知此次加载完成,remove footerView + * + * @param allComplete 是否已加载全部数据 + */ + public void setLoadCompleted(final boolean allComplete) { + if (allComplete && getFooterViewsCount() != 0) { + removeFooterView(loadLayout); + removeFooterView(mLoadCompleteView); + addFooterView(mLoadCompleteView); + } else { + mIsLoadingOrComplete = false; + } + } + + public void updateData() { + mIsLoadingOrComplete = false; + removeFooterView(loadLayout); + removeFooterView(mLoadCompleteView); + } +} + diff --git a/chatapp/src/main/java/jiguang/chat/view/listview/SectionIndexerAdapterWrapper.java b/chatapp/src/main/java/jiguang/chat/view/listview/SectionIndexerAdapterWrapper.java index b50c13f9..ab9d2324 100644 --- a/chatapp/src/main/java/jiguang/chat/view/listview/SectionIndexerAdapterWrapper.java +++ b/chatapp/src/main/java/jiguang/chat/view/listview/SectionIndexerAdapterWrapper.java @@ -3,7 +3,7 @@ import android.content.Context; import android.widget.SectionIndexer; -import jiguang.chat.adapter.StickyListHeadersAdapter; +import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; class SectionIndexerAdapterWrapper extends diff --git a/chatapp/src/main/java/jiguang/chat/view/listview/StickyListHeadersListView.java b/chatapp/src/main/java/jiguang/chat/view/listview/StickyListHeadersListView.java deleted file mode 100644 index 2893d272..00000000 --- a/chatapp/src/main/java/jiguang/chat/view/listview/StickyListHeadersListView.java +++ /dev/null @@ -1,1129 +0,0 @@ -package jiguang.chat.view.listview; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseBooleanArray; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AbsListView.MultiChoiceModeListener; -import android.widget.AbsListView.OnScrollListener; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemLongClickListener; -import android.widget.FrameLayout; -import android.widget.ListView; -import android.widget.SectionIndexer; - -import jiguang.chat.R; -import jiguang.chat.adapter.StickyListHeadersAdapter; - - -/** - * Even though this is a FrameLayout subclass we still consider it a ListView. - * This is because of 2 reasons: - * 1. It acts like as ListView. - * 2. It used to be a ListView subclass and refactoring the name would cause compatibility errors. - * - */ -public class StickyListHeadersListView extends FrameLayout { - - public interface OnHeaderClickListener { - void onHeaderClick(StickyListHeadersListView l, View header, - int itemPosition, long headerId, boolean currentlySticky); - } - - /** - * Notifies the listener when the sticky headers top offset has changed. - */ - public interface OnStickyHeaderOffsetChangedListener { - /** - * @param l The view parent - * @param header The currently sticky header being offset. - * This header is not guaranteed to have it's measurements set. - * It is however guaranteed that this view has been measured, - * therefor you should user getMeasured* methods instead of - * get* methods for determining the view's size. - * @param offset The amount the sticky header is offset by towards to top of the screen. - */ - void onStickyHeaderOffsetChanged(StickyListHeadersListView l, View header, int offset); - } - - /** - * Notifies the listener when the sticky header has been updated - */ - public interface OnStickyHeaderChangedListener { - /** - * @param l The view parent - * @param header The new sticky header view. - * @param itemPosition The position of the item within the adapter's data set of - * the item whose header is now sticky. - * @param headerId The id of the new sticky header. - */ - void onStickyHeaderChanged(StickyListHeadersListView l, View header, - int itemPosition, long headerId); - - } - - /* --- Children --- */ - private WrapperViewList mList; - private View mHeader; - - /* --- Header state --- */ - private Long mHeaderId; - // used to not have to call getHeaderId() all the time - private Integer mHeaderPosition; - private Integer mHeaderOffset; - - /* --- Delegates --- */ - private OnScrollListener mOnScrollListenerDelegate; - private AdapterWrapper mAdapter; - - /* --- Settings --- */ - private boolean mAreHeadersSticky = true; - private boolean mClippingToPadding = true; - private boolean mIsDrawingListUnderStickyHeader = true; - private int mStickyHeaderTopOffset = 0; - private int mPaddingLeft = 0; - private int mPaddingTop = 0; - private int mPaddingRight = 0; - private int mPaddingBottom = 0; - - /* --- Touch handling --- */ - private float mDownY; - private boolean mHeaderOwnsTouch; - private float mTouchSlop; - - /* --- Other --- */ - private OnHeaderClickListener mOnHeaderClickListener; - private OnStickyHeaderOffsetChangedListener mOnStickyHeaderOffsetChangedListener; - private OnStickyHeaderChangedListener mOnStickyHeaderChangedListener; - private AdapterWrapperDataSetObserver mDataSetObserver; - private Drawable mDivider; - private int mDividerHeight; - - public StickyListHeadersListView(Context context) { - this(context, null); - } - - public StickyListHeadersListView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.stickyListHeadersListViewStyle); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public StickyListHeadersListView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); - - // Initialize the wrapped list - mList = new WrapperViewList(context); - - // null out divider, dividers are handled by adapter so they look good with headers - mDivider = mList.getDivider(); - mDividerHeight = mList.getDividerHeight(); - mList.setDivider(null); - mList.setDividerHeight(0); - - if (attrs != null) { - TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.StickyListHeadersListView, defStyle, 0); - - try { - // -- View attributes -- - int padding = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_padding, 0); - mPaddingLeft = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingLeft, padding); - mPaddingTop = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingTop, padding); - mPaddingRight = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingRight, padding); - mPaddingBottom = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_paddingBottom, padding); - - setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom); - - // Set clip to padding on the list and reset value to default on - // wrapper - mClippingToPadding = a.getBoolean(R.styleable.StickyListHeadersListView_android_clipToPadding, true); - super.setClipToPadding(true); - mList.setClipToPadding(mClippingToPadding); - - // scrollbars - final int scrollBars = a.getInt(R.styleable.StickyListHeadersListView_android_scrollbars, 0x00000200); - mList.setVerticalScrollBarEnabled((scrollBars & 0x00000200) != 0); - mList.setHorizontalScrollBarEnabled((scrollBars & 0x00000100) != 0); - - // overscroll - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - mList.setOverScrollMode(a.getInt(R.styleable.StickyListHeadersListView_android_overScrollMode, 0)); - } - - // -- ListView attributes -- - mList.setFadingEdgeLength(a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_fadingEdgeLength, - mList.getVerticalFadingEdgeLength())); - final int fadingEdge = a.getInt(R.styleable.StickyListHeadersListView_android_requiresFadingEdge, 0); - if (fadingEdge == 0x00001000) { - mList.setVerticalFadingEdgeEnabled(false); - mList.setHorizontalFadingEdgeEnabled(true); - } else if (fadingEdge == 0x00002000) { - mList.setVerticalFadingEdgeEnabled(true); - mList.setHorizontalFadingEdgeEnabled(false); - } else { - mList.setVerticalFadingEdgeEnabled(false); - mList.setHorizontalFadingEdgeEnabled(false); - } - mList.setCacheColorHint(a - .getColor(R.styleable.StickyListHeadersListView_android_cacheColorHint, mList.getCacheColorHint())); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mList.setChoiceMode(a.getInt(R.styleable.StickyListHeadersListView_android_choiceMode, - mList.getChoiceMode())); - } - mList.setDrawSelectorOnTop(a.getBoolean(R.styleable.StickyListHeadersListView_android_drawSelectorOnTop, false)); - mList.setFastScrollEnabled(a.getBoolean(R.styleable.StickyListHeadersListView_android_fastScrollEnabled, - mList.isFastScrollEnabled())); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mList.setFastScrollAlwaysVisible(a.getBoolean( - R.styleable.StickyListHeadersListView_android_fastScrollAlwaysVisible, - mList.isFastScrollAlwaysVisible())); - } - -// mList.setScrollBarStyle(a.getInt(R.styleable.StickyListHeadersListView_android_scrollbarStyle, 0)); - - if (a.hasValue(R.styleable.StickyListHeadersListView_android_listSelector)) { - mList.setSelector(a.getDrawable(R.styleable.StickyListHeadersListView_android_listSelector)); - } - - mList.setScrollingCacheEnabled(a.getBoolean(R.styleable.StickyListHeadersListView_android_scrollingCache, - mList.isScrollingCacheEnabled())); - - if (a.hasValue(R.styleable.StickyListHeadersListView_android_divider)) { - mDivider = a.getDrawable(R.styleable.StickyListHeadersListView_android_divider); - } - - mList.setStackFromBottom(a.getBoolean(R.styleable.StickyListHeadersListView_android_stackFromBottom, false)); - - mDividerHeight = a.getDimensionPixelSize(R.styleable.StickyListHeadersListView_android_dividerHeight, - mDividerHeight); - - mList.setTranscriptMode(a.getInt(R.styleable.StickyListHeadersListView_android_transcriptMode, - ListView.TRANSCRIPT_MODE_DISABLED)); - - // -- StickyListHeaders attributes -- - mAreHeadersSticky = a.getBoolean(R.styleable.StickyListHeadersListView_hasStickyHeaders, true); - mIsDrawingListUnderStickyHeader = a.getBoolean( - R.styleable.StickyListHeadersListView_isDrawingListUnderStickyHeader, - true); - } finally { - a.recycle(); - } - } - - // attach some listeners to the wrapped list - mList.setLifeCycleListener(new WrapperViewListLifeCycleListener()); - mList.setOnScrollListener(new WrapperListScrollListener()); - - addView(mList); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - measureHeader(mHeader); - } - - private void ensureHeaderHasCorrectLayoutParams(View header) { - ViewGroup.LayoutParams lp = header.getLayoutParams(); - if (lp == null) { - lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - header.setLayoutParams(lp); - } else if (lp.height == LayoutParams.MATCH_PARENT || lp.width == LayoutParams.WRAP_CONTENT) { - lp.height = LayoutParams.WRAP_CONTENT; - lp.width = LayoutParams.MATCH_PARENT; - header.setLayoutParams(lp); - } - } - - private void measureHeader(View header) { - if (header != null) { - final int width = getMeasuredWidth() - mPaddingLeft - mPaddingRight; - final int parentWidthMeasureSpec = MeasureSpec.makeMeasureSpec( - width, MeasureSpec.EXACTLY); - final int parentHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, - MeasureSpec.UNSPECIFIED); - measureChild(header, parentWidthMeasureSpec, - parentHeightMeasureSpec); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mList.layout(0, 0, mList.getMeasuredWidth(), getHeight()); - if (mHeader != null) { - MarginLayoutParams lp = (MarginLayoutParams) mHeader.getLayoutParams(); - int headerTop = lp.topMargin; - mHeader.layout(mPaddingLeft, headerTop, mHeader.getMeasuredWidth() - + mPaddingLeft, headerTop + mHeader.getMeasuredHeight()); - } - } - - @Override - protected void dispatchDraw(Canvas canvas) { - // Only draw the list here. - // The header should be drawn right after the lists children are drawn. - // This is done so that the header is above the list items - // but below the list decorators (scroll bars etc). - if (mList.getVisibility() == VISIBLE || mList.getAnimation() != null) { - drawChild(canvas, mList, 0); - } - } - - // Reset values tied the header. also remove header form layout - // This is called in response to the data set or the adapter changing - private void clearHeader() { - if (mHeader != null) { - removeView(mHeader); - mHeader = null; - mHeaderId = null; - mHeaderPosition = null; - mHeaderOffset = null; - - // reset the top clipping length - mList.setTopClippingLength(0); - updateHeaderVisibilities(); - } - } - - private void updateOrClearHeader(int firstVisiblePosition) { - final int adapterCount = mAdapter == null ? 0 : mAdapter.getCount(); - if (adapterCount == 0 || !mAreHeadersSticky) { - return; - } - - final int headerViewCount = mList.getHeaderViewsCount(); - int headerPosition = firstVisiblePosition - headerViewCount; - if (mList.getChildCount() > 0) { - View firstItem = mList.getChildAt(0); - if (firstItem.getBottom() < stickyHeaderTop()) { - headerPosition++; - } - } - - // It is not a mistake to call getFirstVisiblePosition() here. - // Most of the time getFixedFirstVisibleItem() should be called - // but that does not work great together with getChildAt() - final boolean doesListHaveChildren = mList.getChildCount() != 0; - final boolean isFirstViewBelowTop = doesListHaveChildren - && mList.getFirstVisiblePosition() == 0 - && mList.getChildAt(0).getTop() >= stickyHeaderTop(); - final boolean isHeaderPositionOutsideAdapterRange = headerPosition > adapterCount - 1 - || headerPosition < 0; - if (!doesListHaveChildren || isHeaderPositionOutsideAdapterRange || isFirstViewBelowTop) { - clearHeader(); - return; - } - - updateHeader(headerPosition); - } - - private void updateHeader(int headerPosition) { - - // check if there is a new header should be sticky - if (mHeaderPosition == null || mHeaderPosition != headerPosition) { - mHeaderPosition = headerPosition; - final long headerId = mAdapter.getHeaderId(headerPosition); - if (mHeaderId == null || mHeaderId != headerId) { - mHeaderId = headerId; - final View header = mAdapter.getHeaderView(mHeaderPosition, mHeader, this); - if (mHeader != header) { - if (header == null) { - throw new NullPointerException("header may not be null"); - } - swapHeader(header); - } - ensureHeaderHasCorrectLayoutParams(mHeader); - measureHeader(mHeader); - if (mOnStickyHeaderChangedListener != null) { - mOnStickyHeaderChangedListener.onStickyHeaderChanged(this, mHeader, headerPosition, mHeaderId); - } - // Reset mHeaderOffset to null ensuring - // that it will be set on the header and - // not skipped for performance reasons. - mHeaderOffset = null; - } - } - - int headerOffset = stickyHeaderTop(); - - // Calculate new header offset - // Skip looking at the first view. it never matters because it always - // results in a headerOffset = 0 - for (int i = 0; i < mList.getChildCount(); i++) { - final View child = mList.getChildAt(i); - final boolean doesChildHaveHeader = child instanceof WrapperView && ((WrapperView) child).hasHeader(); - final boolean isChildFooter = mList.containsFooterView(child); - if (child.getTop() >= stickyHeaderTop() && (doesChildHaveHeader || isChildFooter)) { - headerOffset = Math.min(child.getTop() - mHeader.getMeasuredHeight(), headerOffset); - break; - } - } - - setHeaderOffet(headerOffset); - - if (!mIsDrawingListUnderStickyHeader) { - mList.setTopClippingLength(mHeader.getMeasuredHeight() - + mHeaderOffset); - } - - updateHeaderVisibilities(); - } - - private void swapHeader(View newHeader) { - if (mHeader != null) { - removeView(mHeader); - } - mHeader = newHeader; - addView(mHeader); - if (mOnHeaderClickListener != null) { - mHeader.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mOnHeaderClickListener.onHeaderClick( - StickyListHeadersListView.this, mHeader, - mHeaderPosition, mHeaderId, true); - } - }); - } - mHeader.setClickable(true); - } - - // hides the headers in the list under the sticky header. - // Makes sure the jmui_other ones are showing - private void updateHeaderVisibilities() { - int top = stickyHeaderTop(); - int childCount = mList.getChildCount(); - for (int i = 0; i < childCount; i++) { - - // ensure child is a wrapper view - View child = mList.getChildAt(i); - if (!(child instanceof WrapperView)) { - continue; - } - - // ensure wrapper view child has a header - WrapperView wrapperViewChild = (WrapperView) child; - if (!wrapperViewChild.hasHeader()) { - continue; - } - - // update header views visibility - View childHeader = wrapperViewChild.mHeader; - if (wrapperViewChild.getTop() < top) { - if (childHeader.getVisibility() != View.INVISIBLE) { - childHeader.setVisibility(View.INVISIBLE); - } - } else { - if (childHeader.getVisibility() != View.VISIBLE) { - childHeader.setVisibility(View.VISIBLE); - } - } - } - } - - // Wrapper around setting the header offset in different ways depending on - // the API version - @SuppressLint("NewApi") - private void setHeaderOffet(int offset) { - if (mHeaderOffset == null || mHeaderOffset != offset) { - mHeaderOffset = offset; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mHeader.setTranslationY(mHeaderOffset); - } else { - MarginLayoutParams params = (MarginLayoutParams) mHeader.getLayoutParams(); - params.topMargin = mHeaderOffset; - mHeader.setLayoutParams(params); - } - if (mOnStickyHeaderOffsetChangedListener != null) { - mOnStickyHeaderOffsetChangedListener.onStickyHeaderOffsetChanged(this, mHeader, -mHeaderOffset); - } - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - int action = ev.getAction() & MotionEvent.ACTION_MASK; - if (action == MotionEvent.ACTION_DOWN) { - mDownY = ev.getY(); - mHeaderOwnsTouch = mHeader != null && mDownY <= mHeader.getHeight() + mHeaderOffset; - } - - boolean handled; - if (mHeaderOwnsTouch) { - if (mHeader != null && Math.abs(mDownY - ev.getY()) <= mTouchSlop) { - handled = mHeader.dispatchTouchEvent(ev); - } else { - if (mHeader != null) { - MotionEvent cancelEvent = MotionEvent.obtain(ev); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL); - mHeader.dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - - MotionEvent downEvent = MotionEvent.obtain(ev.getDownTime(), ev.getEventTime(), ev.getAction(), ev.getX(), mDownY, ev.getMetaState()); - downEvent.setAction(MotionEvent.ACTION_DOWN); - handled = mList.dispatchTouchEvent(downEvent); - downEvent.recycle(); - mHeaderOwnsTouch = false; - } - } else { - handled = mList.dispatchTouchEvent(ev); - } - - return handled; - } - - private class AdapterWrapperDataSetObserver extends DataSetObserver { - - @Override - public void onChanged() { - clearHeader(); - } - - @Override - public void onInvalidated() { - clearHeader(); - } - - } - - private class WrapperListScrollListener implements OnScrollListener { - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { - if (mOnScrollListenerDelegate != null) { - mOnScrollListenerDelegate.onScroll(view, firstVisibleItem, - visibleItemCount, totalItemCount); - } - updateOrClearHeader(mList.getFixedFirstVisibleItem()); - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - if (mOnScrollListenerDelegate != null) { - mOnScrollListenerDelegate.onScrollStateChanged(view, - scrollState); - } - } - - } - - private class WrapperViewListLifeCycleListener implements WrapperViewList.LifeCycleListener { - - @Override - public void onDispatchDrawOccurred(Canvas canvas) { - // onScroll is not called often at all before froyo - // therefor we need to update the header here as well. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { - updateOrClearHeader(mList.getFixedFirstVisibleItem()); - } - if (mHeader != null) { - if (mClippingToPadding) { - canvas.save(); - canvas.clipRect(0, mPaddingTop, getRight(), getBottom()); - drawChild(canvas, mHeader, 0); - canvas.restore(); - } else { - drawChild(canvas, mHeader, 0); - } - } - } - - } - - private class AdapterWrapperHeaderClickHandler implements - AdapterWrapper.OnHeaderClickListener { - - @Override - public void onHeaderClick(View header, int itemPosition, long headerId) { - mOnHeaderClickListener.onHeaderClick( - StickyListHeadersListView.this, header, itemPosition, - headerId, false); - } - - } - - private boolean isStartOfSection(int position) { - return position == 0 || mAdapter.getHeaderId(position) != mAdapter.getHeaderId(position - 1); - } - - public int getHeaderOverlap(int position) { - boolean isStartOfSection = isStartOfSection(Math.max(0, position - getHeaderViewsCount())); - if (!isStartOfSection) { - View header = mAdapter.getHeaderView(position, null, mList); - if (header == null) { - throw new NullPointerException("header may not be null"); - } - ensureHeaderHasCorrectLayoutParams(header); - measureHeader(header); - return header.getMeasuredHeight(); - } - return 0; - } - - private int stickyHeaderTop() { - return mStickyHeaderTopOffset + (mClippingToPadding ? mPaddingTop : 0); - } - - /* ---------- StickyListHeaders specific API ---------- */ - - public void setAreHeadersSticky(boolean areHeadersSticky) { - mAreHeadersSticky = areHeadersSticky; - if (!areHeadersSticky) { - clearHeader(); - } else { - updateOrClearHeader(mList.getFixedFirstVisibleItem()); - } - // invalidating the list will trigger dispatchDraw() - mList.invalidate(); - } - - public boolean areHeadersSticky() { - return mAreHeadersSticky; - } - - /** - * Use areHeadersSticky() method instead - */ - @Deprecated - public boolean getAreHeadersSticky() { - return areHeadersSticky(); - } - - /** - * @param stickyHeaderTopOffset The offset of the sticky header fom the top of the view - */ - public void setStickyHeaderTopOffset(int stickyHeaderTopOffset) { - mStickyHeaderTopOffset = stickyHeaderTopOffset; - updateOrClearHeader(mList.getFixedFirstVisibleItem()); - } - - public int getStickyHeaderTopOffset() { - return mStickyHeaderTopOffset; - } - - public void setDrawingListUnderStickyHeader( - boolean drawingListUnderStickyHeader) { - mIsDrawingListUnderStickyHeader = drawingListUnderStickyHeader; - // reset the top clipping length - mList.setTopClippingLength(0); - } - - public boolean isDrawingListUnderStickyHeader() { - return mIsDrawingListUnderStickyHeader; - } - - public void setOnHeaderClickListener(OnHeaderClickListener listener) { - mOnHeaderClickListener = listener; - if (mAdapter != null) { - if (mOnHeaderClickListener != null) { - mAdapter.setOnHeaderClickListener(new AdapterWrapperHeaderClickHandler()); - - if (mHeader != null) { - mHeader.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mOnHeaderClickListener.onHeaderClick( - StickyListHeadersListView.this, mHeader, - mHeaderPosition, mHeaderId, true); - } - }); - } - } else { - mAdapter.setOnHeaderClickListener(null); - } - } - } - - public void setOnStickyHeaderOffsetChangedListener(OnStickyHeaderOffsetChangedListener listener) { - mOnStickyHeaderOffsetChangedListener = listener; - } - - public void setOnStickyHeaderChangedListener(OnStickyHeaderChangedListener listener) { - mOnStickyHeaderChangedListener = listener; - } - - public View getListChildAt(int index) { - return mList.getChildAt(index); - } - - public int getListChildCount() { - return mList.getChildCount(); - } - - /** - * Use the method with extreme caution!! Changing any values on the - * underlying ListView might break everything. - * - * @return the ListView backing this view. - */ - public ListView getWrappedList() { - return mList; - } - - private boolean requireSdkVersion(int versionCode) { - if (Build.VERSION.SDK_INT < versionCode) { - Log.e("StickyListHeaders", "Api lvl must be at least " + versionCode + " to call this method"); - return false; - } - return true; - } - - /* ---------- ListView delegate methods ---------- */ - - public void setAdapter(StickyListHeadersAdapter adapter) { - if (adapter == null) { - if (mAdapter instanceof SectionIndexerAdapterWrapper) { - ((SectionIndexerAdapterWrapper) mAdapter).mSectionIndexerDelegate = null; - } - if (mAdapter != null) { - mAdapter.mDelegate = null; - } - mList.setAdapter(null); - clearHeader(); - return; - } - if (mAdapter != null) { - mAdapter.unregisterDataSetObserver(mDataSetObserver); - } - - if (adapter instanceof SectionIndexer) { - mAdapter = new SectionIndexerAdapterWrapper(getContext(), adapter); - } else { - mAdapter = new AdapterWrapper(getContext(), adapter); - } - mDataSetObserver = new AdapterWrapperDataSetObserver(); - mAdapter.registerDataSetObserver(mDataSetObserver); - - if (mOnHeaderClickListener != null) { - mAdapter.setOnHeaderClickListener(new AdapterWrapperHeaderClickHandler()); - } else { - mAdapter.setOnHeaderClickListener(null); - } - - mAdapter.setDivider(mDivider, mDividerHeight); - - mList.setAdapter(mAdapter); - clearHeader(); - } - - public StickyListHeadersAdapter getAdapter() { - return mAdapter == null ? null : mAdapter.mDelegate; - } - - public void setDivider(Drawable divider) { - mDivider = divider; - if (mAdapter != null) { - mAdapter.setDivider(mDivider, mDividerHeight); - } - } - - public void setDividerHeight(int dividerHeight) { - mDividerHeight = dividerHeight; - if (mAdapter != null) { - mAdapter.setDivider(mDivider, mDividerHeight); - } - } - - public Drawable getDivider() { - return mDivider; - } - - public int getDividerHeight() { - return mDividerHeight; - } - - public void setOnScrollListener(OnScrollListener onScrollListener) { - mOnScrollListenerDelegate = onScrollListener; - } - - @Override - public void setOnTouchListener(final OnTouchListener l) { - if (l != null) { - mList.setOnTouchListener(new OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return l.onTouch(StickyListHeadersListView.this, event); - } - }); - } else { - mList.setOnTouchListener(null); - } - } - - public void setOnItemClickListener(OnItemClickListener listener) { - mList.setOnItemClickListener(listener); - } - - public void setOnItemLongClickListener(OnItemLongClickListener listener) { - mList.setOnItemLongClickListener(listener); - } - - public void addHeaderView(View v, Object data, boolean isSelectable) { - mList.addHeaderView(v, data, isSelectable); - } - - public void addHeaderView(View v) { - mList.addHeaderView(v); - } - - public void removeHeaderView(View v) { - mList.removeHeaderView(v); - } - - public int getHeaderViewsCount() { - return mList.getHeaderViewsCount(); - } - - public void addFooterView(View v, Object data, boolean isSelectable) { - mList.addFooterView(v, data, isSelectable); - } - - public void addFooterView(View v) { - mList.addFooterView(v); - } - - public void removeFooterView(View v) { - mList.removeFooterView(v); - } - - public int getFooterViewsCount() { - return mList.getFooterViewsCount(); - } - - public void setEmptyView(View v) { - mList.setEmptyView(v); - } - - public View getEmptyView() { - return mList.getEmptyView(); - } - - @Override - public boolean isVerticalScrollBarEnabled() { - return mList.isVerticalScrollBarEnabled(); - } - - @Override - public boolean isHorizontalScrollBarEnabled() { - return mList.isHorizontalScrollBarEnabled(); - } - - @Override - public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { - mList.setVerticalScrollBarEnabled(verticalScrollBarEnabled); - } - - @Override - public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { - mList.setHorizontalScrollBarEnabled(horizontalScrollBarEnabled); - } - - @Override - @TargetApi(Build.VERSION_CODES.GINGERBREAD) - public int getOverScrollMode() { - if (requireSdkVersion(Build.VERSION_CODES.GINGERBREAD)) { - return mList.getOverScrollMode(); - } - return 0; - } - - @Override - @TargetApi(Build.VERSION_CODES.GINGERBREAD) - public void setOverScrollMode(int mode) { - if (requireSdkVersion(Build.VERSION_CODES.GINGERBREAD)) { - if (mList != null) { - mList.setOverScrollMode(mode); - } - } - } - - @TargetApi(Build.VERSION_CODES.FROYO) - public void smoothScrollBy(int distance, int duration) { - if (requireSdkVersion(Build.VERSION_CODES.FROYO)) { - mList.smoothScrollBy(distance, duration); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void smoothScrollByOffset(int offset) { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - mList.smoothScrollByOffset(offset); - } - } - - @SuppressLint("NewApi") - @TargetApi(Build.VERSION_CODES.FROYO) - public void smoothScrollToPosition(int position) { - if (requireSdkVersion(Build.VERSION_CODES.FROYO)) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - mList.smoothScrollToPosition(position); - } else { - int offset = mAdapter == null ? 0 : getHeaderOverlap(position); - offset -= mClippingToPadding ? 0 : mPaddingTop; - mList.smoothScrollToPositionFromTop(position, offset); - } - } - } - - @TargetApi(Build.VERSION_CODES.FROYO) - public void smoothScrollToPosition(int position, int boundPosition) { - if (requireSdkVersion(Build.VERSION_CODES.FROYO)) { - mList.smoothScrollToPosition(position, boundPosition); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void smoothScrollToPositionFromTop(int position, int offset) { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - offset += mAdapter == null ? 0 : getHeaderOverlap(position); - offset -= mClippingToPadding ? 0 : mPaddingTop; - mList.smoothScrollToPositionFromTop(position, offset); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void smoothScrollToPositionFromTop(int position, int offset, - int duration) { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - offset += mAdapter == null ? 0 : getHeaderOverlap(position); - offset -= mClippingToPadding ? 0 : mPaddingTop; - mList.smoothScrollToPositionFromTop(position, offset, duration); - } - } - - public void setSelection(int position) { - setSelectionFromTop(position, 0); - } - - public void setSelectionAfterHeaderView() { - mList.setSelectionAfterHeaderView(); - } - - public void setSelectionFromTop(int position, int y) { - y += mAdapter == null ? 0 : getHeaderOverlap(position); - y -= mClippingToPadding ? 0 : mPaddingTop; - mList.setSelectionFromTop(position, y); - } - - public void setSelector(Drawable sel) { - mList.setSelector(sel); - } - - public void setSelector(int resID) { - mList.setSelector(resID); - } - - public int getFirstVisiblePosition() { - return mList.getFirstVisiblePosition(); - } - - public int getLastVisiblePosition() { - return mList.getLastVisiblePosition(); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setChoiceMode(int choiceMode) { - mList.setChoiceMode(choiceMode); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setItemChecked(int position, boolean value) { - mList.setItemChecked(position, value); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public int getCheckedItemCount() { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - return mList.getCheckedItemCount(); - } - return 0; - } - - @TargetApi(11) - public long[] getCheckedItemIds() { - if (requireSdkVersion(Build.VERSION_CODES.FROYO)) { - return mList.getCheckedItemIds(); - } - return null; - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public int getCheckedItemPosition() { - return mList.getCheckedItemPosition(); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public SparseBooleanArray getCheckedItemPositions() { - return mList.getCheckedItemPositions(); - } - - public int getCount() { - return mList.getCount(); - } - - public Object getItemAtPosition(int position) { - return mList.getItemAtPosition(position); - } - - public long getItemIdAtPosition(int position) { - return mList.getItemIdAtPosition(position); - } - - @Override - public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { - mList.setOnCreateContextMenuListener(l); - } - - @Override - public boolean showContextMenu() { - return mList.showContextMenu(); - } - - public void invalidateViews() { - mList.invalidateViews(); - } - - @Override - public void setClipToPadding(boolean clipToPadding) { - if (mList != null) { - mList.setClipToPadding(clipToPadding); - } - mClippingToPadding = clipToPadding; - } - - @Override - public void setPadding(int left, int top, int right, int bottom) { - mPaddingLeft = left; - mPaddingTop = top; - mPaddingRight = right; - mPaddingBottom = bottom; - - if (mList != null) { - mList.setPadding(left, top, right, bottom); - } - super.setPadding(0, 0, 0, 0); - requestLayout(); - } - - /* - * Overrides an @hide method in View - */ - protected void recomputePadding() { - setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom); - } - - @Override - public int getPaddingLeft() { - return mPaddingLeft; - } - - @Override - public int getPaddingTop() { - return mPaddingTop; - } - - @Override - public int getPaddingRight() { - return mPaddingRight; - } - - @Override - public int getPaddingBottom() { - return mPaddingBottom; - } - - public void setFastScrollEnabled(boolean fastScrollEnabled) { - mList.setFastScrollEnabled(fastScrollEnabled); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setFastScrollAlwaysVisible(boolean alwaysVisible) { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - mList.setFastScrollAlwaysVisible(alwaysVisible); - } - } - - /** - * @return true if the fast scroller will always show. False on pre-Honeycomb devices. - * @see AbsListView#isFastScrollAlwaysVisible() - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public boolean isFastScrollAlwaysVisible() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - return false; - } - return mList.isFastScrollAlwaysVisible(); - } - - public void setScrollBarStyle(int style) { - mList.setScrollBarStyle(style); - } - - public int getScrollBarStyle() { - return mList.getScrollBarStyle(); - } - - public int getPositionForView(View view) { - return mList.getPositionForView(view); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setMultiChoiceModeListener(MultiChoiceModeListener listener) { - if (requireSdkVersion(Build.VERSION_CODES.HONEYCOMB)) { - mList.setMultiChoiceModeListener(listener); - } - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - if (superState != BaseSavedState.EMPTY_STATE) { - throw new IllegalStateException("Handling non empty state of parent class is not implemented"); - } - return mList.onSaveInstanceState(); - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - super.onRestoreInstanceState(BaseSavedState.EMPTY_STATE); - mList.onRestoreInstanceState(state); - } - - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public boolean canScrollVertically(int direction) { - return mList.canScrollVertically(direction); - } - - public void setTranscriptMode(int mode) { - mList.setTranscriptMode(mode); - } - - public void setBlockLayoutChildren(boolean blockLayoutChildren) { - mList.setBlockLayoutChildren(blockLayoutChildren); - } - - public void setStackFromBottom(boolean stackFromBottom) { - mList.setStackFromBottom(stackFromBottom); - } - - public boolean isStackFromBottom() { - return mList.isStackFromBottom(); - } -} diff --git a/chatapp/src/main/res/drawable-xxhdpi/chat_room_avatar.png b/chatapp/src/main/res/drawable-xxhdpi/chat_room_avatar.png new file mode 100644 index 00000000..495ac783 Binary files /dev/null and b/chatapp/src/main/res/drawable-xxhdpi/chat_room_avatar.png differ diff --git a/chatapp/src/main/res/drawable-xxhdpi/conversation_normal.png b/chatapp/src/main/res/drawable-xxhdpi/conversation_normal.png new file mode 100644 index 00000000..b333ef48 Binary files /dev/null and b/chatapp/src/main/res/drawable-xxhdpi/conversation_normal.png differ diff --git a/chatapp/src/main/res/drawable-xxhdpi/conversation_press.png b/chatapp/src/main/res/drawable-xxhdpi/conversation_press.png new file mode 100644 index 00000000..e822a4f3 Binary files /dev/null and b/chatapp/src/main/res/drawable-xxhdpi/conversation_press.png differ diff --git a/chatapp/src/main/res/drawable-xxhdpi/open_group.png b/chatapp/src/main/res/drawable-xxhdpi/open_group.png new file mode 100644 index 00000000..efd6b7cf Binary files /dev/null and b/chatapp/src/main/res/drawable-xxhdpi/open_group.png differ diff --git a/chatapp/src/main/res/drawable-xxhdpi/update_avatar.png b/chatapp/src/main/res/drawable-xxhdpi/update_avatar.png new file mode 100644 index 00000000..e7fcc26a Binary files /dev/null and b/chatapp/src/main/res/drawable-xxhdpi/update_avatar.png differ diff --git a/chatapp/src/main/res/drawable/actionbar_conversation_bg.xml b/chatapp/src/main/res/drawable/actionbar_conversation_bg.xml new file mode 100644 index 00000000..947e6ab2 --- /dev/null +++ b/chatapp/src/main/res/drawable/actionbar_conversation_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/actionbar_me_drawable_bg.xml b/chatapp/src/main/res/drawable/actionbar_me_drawable_bg.xml index 4928783a..6993afab 100644 --- a/chatapp/src/main/res/drawable/actionbar_me_drawable_bg.xml +++ b/chatapp/src/main/res/drawable/actionbar_me_drawable_bg.xml @@ -1,7 +1,6 @@ - - - + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/border_bg.xml b/chatapp/src/main/res/drawable/border_bg.xml new file mode 100644 index 00000000..73510c93 --- /dev/null +++ b/chatapp/src/main/res/drawable/border_bg.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/bottom_line.xml b/chatapp/src/main/res/drawable/bottom_line.xml new file mode 100644 index 00000000..d73d1364 --- /dev/null +++ b/chatapp/src/main/res/drawable/bottom_line.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/bottom_line_normal.xml b/chatapp/src/main/res/drawable/bottom_line_normal.xml new file mode 100644 index 00000000..c304cbe7 --- /dev/null +++ b/chatapp/src/main/res/drawable/bottom_line_normal.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/edittext.xml b/chatapp/src/main/res/drawable/edittext.xml index fc962c21..c8888da8 100644 --- a/chatapp/src/main/res/drawable/edittext.xml +++ b/chatapp/src/main/res/drawable/edittext.xml @@ -1,4 +1,3 @@ - \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/jmui_remove_btn_bg.xml b/chatapp/src/main/res/drawable/jmui_remove_btn_bg.xml new file mode 100644 index 00000000..0e453255 --- /dev/null +++ b/chatapp/src/main/res/drawable/jmui_remove_btn_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/selector_home_title_line.xml b/chatapp/src/main/res/drawable/selector_home_title_line.xml new file mode 100644 index 00000000..dba6c6ec --- /dev/null +++ b/chatapp/src/main/res/drawable/selector_home_title_line.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/switch_thumb.xml b/chatapp/src/main/res/drawable/switch_thumb.xml new file mode 100644 index 00000000..80ae6554 --- /dev/null +++ b/chatapp/src/main/res/drawable/switch_thumb.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/switch_track.xml b/chatapp/src/main/res/drawable/switch_track.xml new file mode 100644 index 00000000..c211ed07 --- /dev/null +++ b/chatapp/src/main/res/drawable/switch_track.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/switch_track_off.xml b/chatapp/src/main/res/drawable/switch_track_off.xml new file mode 100644 index 00000000..6a6a7a4d --- /dev/null +++ b/chatapp/src/main/res/drawable/switch_track_off.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/switch_track_on.xml b/chatapp/src/main/res/drawable/switch_track_on.xml new file mode 100644 index 00000000..7292eefc --- /dev/null +++ b/chatapp/src/main/res/drawable/switch_track_on.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/drawable/text_selector.xml b/chatapp/src/main/res/drawable/text_selector.xml new file mode 100644 index 00000000..6e2a83ec --- /dev/null +++ b/chatapp/src/main/res/drawable/text_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/chatapp/src/main/res/layout/activity_apply_group_info.xml b/chatapp/src/main/res/layout/activity_apply_group_info.xml new file mode 100644 index 00000000..cf50b019 --- /dev/null +++ b/chatapp/src/main/res/layout/activity_apply_group_info.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +