PageRenderTime 69ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/dateLoveInternational/src/main/java/com/datelove/online/International/activity/ChatActivity.java

https://bitbucket.org/juzhiwiscom/datelove
Java | 1127 lines | 895 code | 84 blank | 148 comment | 128 complexity | 27fbcdeab31ec6a3632f356889041200 MD5 | raw file
  1. package com.datelove.online.International.activity;
  2. import android.Manifest;
  3. import android.app.Activity;
  4. import android.app.Dialog;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.content.pm.PackageManager;
  8. import android.graphics.Color;
  9. import android.graphics.drawable.AnimationDrawable;
  10. import android.graphics.drawable.ColorDrawable;
  11. import android.graphics.drawable.Drawable;
  12. import android.net.Uri;
  13. import android.os.Bundle;
  14. import android.os.Handler;
  15. import android.os.Vibrator;
  16. import android.support.annotation.NonNull;
  17. import android.support.v4.app.ActivityCompat;
  18. import android.support.v4.content.ContextCompat;
  19. import android.support.v4.widget.SwipeRefreshLayout;
  20. import android.support.v7.widget.LinearLayoutManager;
  21. import android.support.v7.widget.RecyclerView;
  22. import android.text.TextUtils;
  23. import android.view.Display;
  24. import android.view.Gravity;
  25. import android.view.LayoutInflater;
  26. import android.view.MotionEvent;
  27. import android.view.View;
  28. import android.view.Window;
  29. import android.view.WindowManager;
  30. import android.widget.AdapterView;
  31. import android.widget.Button;
  32. import android.widget.ImageView;
  33. import android.widget.PopupWindow;
  34. import android.widget.RelativeLayout;
  35. import android.widget.TextView;
  36. import com.alibaba.fastjson.JSON;
  37. import com.datelove.online.International.R;
  38. import com.datelove.online.International.adapter.ChatAdapter;
  39. import com.datelove.online.International.base.BaseTitleActivity;
  40. import com.datelove.online.International.bean.BaseModel;
  41. import com.datelove.online.International.bean.Image;
  42. import com.datelove.online.International.bean.Message;
  43. import com.datelove.online.International.bean.MessageList;
  44. import com.datelove.online.International.bean.WriteMsg;
  45. import com.datelove.online.International.constant.IConfigConstant;
  46. import com.datelove.online.International.constant.IUrlConstant;
  47. import com.datelove.online.International.event.MessageChangedEvent;
  48. import com.datelove.online.International.event.RefreshChatDialogEvent;
  49. import com.datelove.online.International.event.RefreshChatEvent;
  50. import com.datelove.online.International.haoping.ActionSheetDialog;
  51. import com.datelove.online.International.haoping.OnOperItemClickL;
  52. import com.datelove.online.International.utils.FileUtil;
  53. import com.datelove.online.International.utils.RecordUtil;
  54. import com.datelove.online.International.utils.Utils;
  55. import com.datelove.online.International.xml.PlatformInfoXml;
  56. import com.datelove.online.International.xml.UserInfoXml;
  57. import com.library.dialog.OnDoubleDialogClickListener;
  58. import com.library.utils.DialogUtil;
  59. import com.library.utils.LogUtil;
  60. import com.library.utils.SharedPreferenceUtil;
  61. import com.library.utils.ToastUtil;
  62. import com.library.utils.Util;
  63. import com.library.utils.VersionInfoUtil;
  64. import com.library.widgets.AutoSwipeRefreshLayout;
  65. import com.library.widgets.ClearableEditText;
  66. import com.zhy.http.okhttp.OkHttpUtils;
  67. import com.zhy.http.okhttp.callback.Callback;
  68. import org.greenrobot.eventbus.EventBus;
  69. import org.greenrobot.eventbus.Subscribe;
  70. import java.io.File;
  71. import java.util.ArrayList;
  72. import java.util.HashMap;
  73. import java.util.List;
  74. import java.util.Map;
  75. import butterknife.BindView;
  76. import butterknife.ButterKnife;
  77. import butterknife.OnClick;
  78. import okhttp3.Call;
  79. import okhttp3.Response;
  80. /**
  81. * 聊天页面
  82. * Created by zhangdroid on 2016/11/2.
  83. */
  84. public class ChatActivity extends BaseTitleActivity {
  85. @BindView(R.id.chat_swiperefresh)
  86. AutoSwipeRefreshLayout mAutoSwipeRefresh;
  87. @BindView(R.id.chat_RecyclerView)
  88. RecyclerView mRecyclerView;
  89. @BindView(R.id.chat_bottom_bar)
  90. RelativeLayout mRlChatBottom;
  91. @BindView(R.id.chat_operate_container)
  92. RelativeLayout mRlChatContainer;
  93. @BindView(R.id.chat_et_input)
  94. ClearableEditText mEtInput;
  95. @BindView(R.id.chat_send_msg)
  96. Button mBtnSend;// 发送文字消息
  97. @BindView(R.id.chat_send_photo)
  98. ImageView mIvSendPhoto;// 发送图片
  99. @BindView(R.id.chat_intercept)
  100. TextView mTvIntercept;
  101. // 语音
  102. @BindView(R.id.chat_msg_switch)
  103. ImageView mIvChatSwitch;
  104. @BindView(R.id.record)
  105. Button mBtnRecord;
  106. /**
  107. * 用户id
  108. */
  109. private String mUserId;
  110. /**
  111. * 用户昵称
  112. */
  113. private String mNickname;
  114. /**
  115. * 用户头像url
  116. */
  117. private String mAvatarUrl;
  118. private ChatAdapter mChatAdapter;
  119. private LinearLayoutManager mLinearLayoutManager;
  120. // 录音框
  121. private PopupWindow mRecordPopupWindow;
  122. private static final int PERMISSION_CODE_RECORD_AUDIO = 0;
  123. private static final int PERMISSION_CODE_WRITE_EXTERNAL_STORAGE = 1;
  124. private static final int MSG_TYPE_TIMER = 1;
  125. // 录音文件路径
  126. private String mOutputPath;
  127. // 录音文件名
  128. private String mRecordFileName;
  129. // 是否正在录音
  130. private boolean mIsRecording;
  131. // 录音是否被取消
  132. private boolean mIsRecordCanceled;
  133. // 录音时长(毫秒)
  134. private long mRecordDuration;
  135. // 录音计时刷新间隔(毫秒)
  136. private final long mRefreshInterval = 250;
  137. // 计算录音时长的Handler
  138. private Handler mTimerHandler = new Handler() {
  139. @Override
  140. public void handleMessage(android.os.Message msg) {
  141. super.handleMessage(msg);
  142. switch (msg.what) {
  143. case MSG_TYPE_TIMER:
  144. if (mIsRecording) {
  145. // 计时
  146. mRecordDuration += mRefreshInterval;
  147. // 录音超过1分钟自动发送
  148. if (mRecordDuration > 60 * 1000) {
  149. stopRecordAndSend();
  150. } else {
  151. mTimerHandler.sendEmptyMessageDelayed(MSG_TYPE_TIMER, mRefreshInterval);
  152. }
  153. }
  154. break;
  155. }
  156. }
  157. };
  158. private boolean showDialog=false;
  159. private Dialog dialog;
  160. private String isUpdateUnPay="0";
  161. @Override
  162. protected void onCreate(Bundle savedInstanceState) {
  163. super.onCreate(savedInstanceState);
  164. // TODO: add setContentView(...) invocation
  165. ButterKnife.bind(this);
  166. }
  167. // 录音状态常量
  168. private enum STATE {
  169. /**
  170. * 默认值
  171. */
  172. IDLE,
  173. /**
  174. * 录音中
  175. */
  176. RECORDING,
  177. /**
  178. * 取消
  179. */
  180. CANCELED,
  181. /**
  182. * 录音时间太短
  183. */
  184. TOO_SHORT
  185. }
  186. private boolean mIsShowSendVipByPraise = false;
  187. private boolean mIsShowWriteMsgIntercept = false;
  188. private static final String INTENT_KEY_UID = "key_userId";
  189. private static final String INTENT_KEY_NICKNAME = "key_nickname";
  190. private static final String INTENT_KEY_AVATAR_URL = "key_avatar_url";
  191. String country = PlatformInfoXml.getPlatformInfo().getCountry().trim();
  192. /**
  193. * 跳转聊天页
  194. *
  195. * @param from
  196. * @param userId 用户id
  197. * @param nickname 用户昵称
  198. * @param avatarUrl 用户头像url
  199. */
  200. public static void toChatActivity(Activity from, String userId, String nickname, String avatarUrl) {
  201. Map<String, String> map = new HashMap<String, String>();
  202. map.put(INTENT_KEY_UID, userId);
  203. map.put(INTENT_KEY_NICKNAME, nickname);
  204. map.put(INTENT_KEY_AVATAR_URL, avatarUrl);
  205. Util.gotoActivity(from, ChatActivity.class, false, map);
  206. }
  207. /**
  208. * 跳转聊天页
  209. *
  210. * @param context
  211. * @param userId 用户id
  212. * @param nickname 用户昵称
  213. * @param avatarUrl 用户头像url
  214. */
  215. public static void toChatActivity(Context context, String userId, String nickname, String avatarUrl) {
  216. Intent intent = new Intent(context, ChatActivity.class);
  217. intent.putExtra(INTENT_KEY_UID, userId);
  218. intent.putExtra(INTENT_KEY_NICKNAME, nickname);
  219. intent.putExtra(INTENT_KEY_AVATAR_URL, avatarUrl);
  220. context.startActivity(intent);
  221. }
  222. @Override
  223. protected int getLayoutResId() {
  224. return R.layout.activity_chat;
  225. }
  226. @Override
  227. protected String getCenterTitle() {
  228. return null;
  229. }
  230. @Override
  231. protected void initViewsAndVariables() {
  232. Intent intent = getIntent();
  233. if (intent != null) {
  234. mUserId = intent.getStringExtra(INTENT_KEY_UID);
  235. mNickname = intent.getStringExtra(INTENT_KEY_NICKNAME);
  236. mAvatarUrl = intent.getStringExtra(INTENT_KEY_AVATAR_URL);
  237. }
  238. if (!TextUtils.isEmpty(mNickname)) {
  239. setTitle(mNickname);
  240. }
  241. // 设置下拉刷新动画样式
  242. mAutoSwipeRefresh.setColorSchemeResources(R.color.main_color);
  243. mAutoSwipeRefresh.setProgressBackgroundColorSchemeColor(Color.WHITE);
  244. mLinearLayoutManager = new LinearLayoutManager(this);
  245. mLinearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
  246. mRecyclerView.setLayoutManager(mLinearLayoutManager);
  247. mChatAdapter = new ChatAdapter(this, -1);
  248. mRecyclerView.setAdapter(mChatAdapter);
  249. if(country.equals(getString(R.string.united_states).trim()) || country.equals("America")){
  250. if(UserInfoXml.getSearchInterceptor()){
  251. /**加载读信拦截对话框**/
  252. boolean showDalog = SharedPreferenceUtil.getBooleanValue(Utils.getContext(), "INTERCEPT_DIALOG", "DIALOG", true);
  253. if(showDalog){
  254. isUpdateUnPay="0";
  255. showDialog();
  256. }else{
  257. isUpdateUnPay="1";
  258. isShowDialog();
  259. }
  260. }else{
  261. isUpdateUnPay="1";
  262. isShowDialog();
  263. }
  264. }else{
  265. /**加载读信拦截对话框**/
  266. boolean showDalog = SharedPreferenceUtil.getBooleanValue(Utils.getContext(), "INTERCEPT_DIALOG", "DIALOG", true);
  267. if(showDalog){
  268. isUpdateUnPay="0";
  269. showDialog();
  270. }else{
  271. isUpdateUnPay="1";
  272. isShowDialog();
  273. }
  274. }
  275. }
  276. /**加载读信拦截的对话框**/
  277. private void showDialog() {
  278. dialog= new Dialog(this);
  279. LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
  280. View v=li.inflate(R.layout.dialog_layout, null);
  281. dialog.setContentView(v);
  282. ImageView ivBack = (ImageView)v.findViewById(R.id.iv_back);
  283. Button btnUpgrade = (Button)v.findViewById(R.id.btn_upgrade);
  284. ivBack.setOnClickListener(new View.OnClickListener() {
  285. @Override
  286. public void onClick(View view) {
  287. mRecyclerView.setVisibility(View.GONE);
  288. EventBus.getDefault().post(new MessageChangedEvent());
  289. finish();
  290. // dialog.dismiss();
  291. }
  292. });
  293. btnUpgrade.setOnClickListener(new View.OnClickListener() {
  294. @Override
  295. public void onClick(View view) {
  296. //添加好评送会员
  297. if (mIsShowSendVipByPraise) {
  298. ActionSheetDialogNoTitle();
  299. } else {
  300. BuyServiceActivity.toBuyServiceActivity(ChatActivity.this, BuyServiceActivity.INTENT_FROM_INTERCEPT,
  301. IConfigConstant.PAY_TAG_FROM_CHAT, IConfigConstant.PAY_WAY_ALL);
  302. }
  303. }
  304. });
  305. Window dialogWindow = dialog.getWindow();
  306. WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
  307. dialogWindow.setGravity(Gravity.LEFT | Gravity.BOTTOM);
  308. /*
  309. * 将对话框的大小按屏幕大小的百分比设置
  310. */
  311. WindowManager m = getWindowManager();
  312. Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
  313. p.height = (int) (d.getHeight() * 0.6); // 高度设置为屏幕的0.6
  314. p.width = (int) (d.getWidth() * 0.8); // 宽度设置为屏幕的0.65
  315. p.x = (int) (d.getWidth() * 0.135); // 新位置X坐标
  316. p.y = (int) (d.getHeight() * 0.27); // 新位置Y坐标
  317. // p.y = (int) (d.getHeight() * 0.1); // 新位置Y坐标
  318. // p.alpha = 1.0f; // 透明度
  319. // p.dimAmount = 0.7f;//黑暗度
  320. dialogWindow.setAttributes(p);
  321. // getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
  322. // WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
  323. // getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
  324. dialog.setCancelable(false);
  325. dialog.show();
  326. }
  327. /**根据是否是会员来判断拦截对话框的显示与否**/
  328. private void isShowDialog() {
  329. OkHttpUtils.post()
  330. .url(IUrlConstant.URL_GET_CHAT_MSG)
  331. .addHeader("token", PlatformInfoXml.getToken())
  332. .addParams("platformInfo", PlatformInfoXml.getPlatformJsonString())
  333. .addParams("uid", mUserId)
  334. .addParams("isUpdateUnPay", isUpdateUnPay)
  335. .addParams("matcherIsRead", "-1")
  336. .build()
  337. .execute(new Callback<MessageList>() {
  338. @Override
  339. public MessageList parseNetworkResponse(Response response, int id) throws Exception {
  340. String resultJson = response.body().string();
  341. if (!TextUtils.isEmpty(resultJson)) {
  342. return JSON.parseObject(resultJson, MessageList.class);
  343. }
  344. return null;
  345. }
  346. @Override
  347. public void onError(Call call, Exception e, int id) {
  348. stopRefresh(3);
  349. }
  350. @Override
  351. public void onResponse(MessageList response, int id) {
  352. if (response != null) {
  353. // 设置支付拦截
  354. String intercept = response.getShowWriteMsgIntercept();
  355. if (!TextUtils.isEmpty(intercept) && "1".equals(intercept)) {
  356. if(country.equals(getString(R.string.united_states).trim()) || country.equals("America")){
  357. if(UserInfoXml.getSearchInterceptor()){
  358. showDialog();
  359. if(UserInfoXml.isMale()){
  360. SharedPreferenceUtil.setBooleanValue(Utils.getContext(), "INTERCEPT_DIALOG", "DIALOG", true);
  361. }
  362. }else{
  363. // 美国拦截;展示拦截窗口
  364. mTvIntercept.setVisibility(View.VISIBLE);
  365. mIsShowWriteMsgIntercept = true;
  366. mRlChatContainer.setVisibility(View.GONE);
  367. }
  368. }else{
  369. showDialog();
  370. if(UserInfoXml.isMale()){
  371. SharedPreferenceUtil.setBooleanValue(Utils.getContext(), "INTERCEPT_DIALOG", "DIALOG", true);
  372. }
  373. }
  374. } else {
  375. // 不展示拦截入口
  376. // dialog.dismiss();
  377. // showDialog=false;
  378. }
  379. }
  380. // stopRefresh(1);
  381. }
  382. });
  383. }
  384. @Override
  385. protected void addListeners() {
  386. mIvLeft.setOnClickListener(new View.OnClickListener() {
  387. @Override
  388. public void onClick(View view) {
  389. EventBus.getDefault().post(new MessageChangedEvent());
  390. finish();
  391. }
  392. });
  393. mAutoSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  394. @Override
  395. public void onRefresh() {
  396. loadMsgList();
  397. }
  398. });
  399. // 处理滑动冲突
  400. mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
  401. @Override
  402. public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
  403. super.onScrollStateChanged(recyclerView, newState);
  404. }
  405. @Override
  406. public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  407. super.onScrolled(recyclerView, dx, dy);
  408. // 判断是否滑动到顶部
  409. int scrolledPosition = (mRecyclerView == null || mRecyclerView.getChildCount() == 0) ? 0 : mRecyclerView.getChildAt(0).getTop();
  410. mAutoSwipeRefresh.setEnabled(scrolledPosition >= 0);
  411. }
  412. });
  413. // 发送文字消息
  414. mEtInput.setTextWatcherCallback(new ClearableEditText.TextWatcherCallback() {
  415. @Override
  416. public void handleTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
  417. if (mEtInput.length() > 0) {
  418. mBtnSend.setVisibility(View.VISIBLE);
  419. mIvSendPhoto.setVisibility(View.GONE);
  420. } else {
  421. mBtnSend.setVisibility(View.GONE);
  422. mIvSendPhoto.setVisibility(View.VISIBLE);
  423. }
  424. }
  425. });
  426. // 切换文字/语音
  427. mIvChatSwitch.setOnClickListener(new View.OnClickListener() {
  428. @Override
  429. public void onClick(View v) {
  430. mIvChatSwitch.setSelected(!mIvChatSwitch.isSelected());
  431. if (mIvChatSwitch.isSelected()) { // 显示发送语音
  432. mBtnRecord.setText(getString(R.string.press_to_speak));
  433. mBtnRecord.setVisibility(View.VISIBLE);
  434. mEtInput.setVisibility(View.GONE);
  435. mBtnSend.setVisibility(View.GONE);
  436. mIvSendPhoto.setVisibility(View.GONE);
  437. if (mIsShowWriteMsgIntercept) {// 支付拦截时不可用
  438. mBtnRecord.setClickable(false);
  439. mBtnRecord.setEnabled(false);
  440. mBtnRecord.setTextColor(getResources().getColor(R.color.textcolor_light_gray));
  441. } else {
  442. mBtnRecord.setClickable(true);
  443. mBtnRecord.setEnabled(true);
  444. mBtnRecord.setTextColor(getResources().getColor(R.color.main_color));
  445. }
  446. } else { // 显示输入框
  447. mBtnRecord.setVisibility(View.GONE);
  448. mEtInput.setVisibility(View.VISIBLE);
  449. // mEtInput.setFocusable(true);
  450. // mEtInput.setFocusableInTouchMode(true);
  451. // mEtInput.requestFocus();
  452. // ChatActivity.this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
  453. if (mEtInput.getText().length() > 0) {
  454. // 已经输入文字
  455. mBtnSend.setVisibility(View.VISIBLE);
  456. mIvSendPhoto.setVisibility(View.GONE);
  457. } else {
  458. mBtnSend.setVisibility(View.GONE);
  459. mIvSendPhoto.setVisibility(View.VISIBLE);
  460. }
  461. }
  462. }
  463. });
  464. // 发送语音消息
  465. mBtnRecord.setOnTouchListener(new View.OnTouchListener() {
  466. @Override
  467. public boolean onTouch(View v, MotionEvent event) {
  468. // 检查权限
  469. if (!checkPermissions()) {// 请求权限时不录音
  470. switch (event.getAction()) {
  471. case MotionEvent.ACTION_DOWN:// 按下时开始录音
  472. mBtnRecord.setText(getString(R.string.loose_to_end));
  473. showRecordPopupWindow(STATE.RECORDING);
  474. startRecord();
  475. mIsRecordCanceled = false;
  476. LogUtil.e(LogUtil.TAG_ZL, "ACTION_DOWN start()");
  477. break;
  478. case MotionEvent.ACTION_MOVE:
  479. if (event.getY() < -100) { // 上滑取消发送
  480. mIsRecordCanceled = true;
  481. showRecordPopupWindow(STATE.CANCELED);
  482. } else {
  483. mIsRecordCanceled = false;
  484. showRecordPopupWindow(STATE.RECORDING);
  485. }
  486. LogUtil.e(LogUtil.TAG_ZL, "ACTION_MOVE " + event.getY() + " mIsRecordCanceled = " + mIsRecordCanceled);
  487. break;
  488. case MotionEvent.ACTION_UP:// 松开时停止录音并发送
  489. mBtnRecord.setText(getString(R.string.press_to_speak));
  490. if (mIsRecordCanceled) {
  491. cancelRecord();
  492. LogUtil.e(LogUtil.TAG_ZL, "ACTION_UP canceld()");
  493. } else {
  494. stopRecordAndSend();
  495. LogUtil.e(LogUtil.TAG_ZL, "ACTION_UP stop()");
  496. }
  497. break;
  498. }
  499. }
  500. return true;
  501. }
  502. });
  503. // 发送图片
  504. mIvSendPhoto.setOnClickListener(new View.OnClickListener() {
  505. @Override
  506. public void onClick(View v) {
  507. GetPhotoActivity.toGetPhotoActivity(ChatActivity.this, IConfigConstant.LOCAL_PIC_PATH, new GetPhotoActivity.OnGetPhotoListener() {
  508. @Override
  509. public void getSelectedPhoto(File file) {
  510. if (file != null) {
  511. // 发送图片前显示要发送的图片进度
  512. Message message = new Message();
  513. if (mChatAdapter != null) {
  514. mChatAdapter.isShowImgLoading(true);
  515. mChatAdapter.isShowImgRetry(false);
  516. message.setUid(UserInfoXml.getUID());
  517. message.setMsgType("10");
  518. message.setCreateDateMills(System.currentTimeMillis());
  519. Image image = new Image();
  520. image.setIsMain(2);
  521. image.setThumbnailUrl(file.getAbsolutePath());
  522. image.setThumbnailUrlM(file.getAbsolutePath());
  523. image.setImageUrl(file.getAbsolutePath());
  524. message.setChatImage(image);
  525. mChatAdapter.insertItem(mChatAdapter.getItemCount(), message);
  526. // 滚动到底部
  527. mLinearLayoutManager.scrollToPosition(mChatAdapter.getItemCount() - 1);
  528. }
  529. sendPhotoMsg(file, message);
  530. }
  531. }
  532. });
  533. }
  534. });
  535. }
  536. private boolean checkPermissions() {
  537. boolean needRequestPermission = false;
  538. if (ContextCompat.checkSelfPermission(ChatActivity.this.getApplicationContext(),
  539. Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_DENIED) {
  540. needRequestPermission = true;
  541. // 请求android.permission.RECORD_AUDIO权限
  542. ActivityCompat.requestPermissions(ChatActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSION_CODE_RECORD_AUDIO);
  543. }
  544. if (ContextCompat.checkSelfPermission(ChatActivity.this.getApplicationContext(),
  545. Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
  546. needRequestPermission = true;
  547. // 请求android.permission.WRITE_EXTERNAL_STORAGE权限
  548. ActivityCompat.requestPermissions(ChatActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_CODE_WRITE_EXTERNAL_STORAGE);
  549. }
  550. return needRequestPermission;
  551. }
  552. @Override
  553. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  554. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  555. }
  556. /**
  557. * 开始录音
  558. */
  559. private void startRecord() {
  560. // 录音开始前震动一下
  561. Vibrator vibrator = (Vibrator) ChatActivity.this.getSystemService(Context.VIBRATOR_SERVICE);
  562. vibrator.vibrate(88);
  563. // 根据系统时间生成文件名
  564. mRecordFileName = FileUtil.createFileNameByTime() + ".mp3";
  565. // 录音文件保存路径: 根目录/DateLove/record/用户id/xxx.mp3
  566. mOutputPath = FileUtil.RECORD_DIRECTORY_PATH + File.separator + UserInfoXml.getUID() + File.separator + mRecordFileName;
  567. LogUtil.e(LogUtil.TAG_ZL, "录音存放路径:" + mOutputPath);
  568. // 开始录音
  569. RecordUtil.getInstance().startRecord(mOutputPath);
  570. mIsRecording = true;
  571. mRecordDuration = 0;
  572. // 计时,间隔250毫秒刷新
  573. mTimerHandler.sendEmptyMessageDelayed(MSG_TYPE_TIMER, mRefreshInterval);
  574. }
  575. /**
  576. * 停止录音并发送
  577. */
  578. private void stopRecordAndSend() {
  579. if (mIsRecording) {
  580. mIsRecording = false;
  581. LogUtil.e(LogUtil.TAG_ZL, "录音时长(毫秒):" + mRecordDuration);
  582. if (mRecordDuration < 1 * 1000) {// 录音时长小于1秒的不发送
  583. showRecordPopupWindow(STATE.TOO_SHORT);
  584. new Handler().postDelayed(new Runnable() {
  585. @Override
  586. public void run() {
  587. // 延时500毫秒调用MediaRecorder#stop(),防止出现start()之后立马调用stop()的异常
  588. RecordUtil.getInstance().stopRecord();
  589. // 删除小于1秒的文件
  590. FileUtil.deleteFile(mOutputPath);
  591. }
  592. }, 500);
  593. } else {// 发送语音
  594. RecordUtil.getInstance().stopRecord();
  595. sendVoiceMsg();
  596. }
  597. // 隐藏录音框
  598. new Handler().postDelayed(new Runnable() {
  599. @Override
  600. public void run() {
  601. if (mRecordPopupWindow != null && mRecordPopupWindow.isShowing()) {
  602. mRecordPopupWindow.dismiss();
  603. }
  604. }
  605. }, 500);
  606. }
  607. }
  608. /**
  609. * 录音取消,删除已经录制的文件
  610. */
  611. private void cancelRecord() {
  612. if (mIsRecordCanceled) {
  613. RecordUtil.getInstance().stopRecord();
  614. mIsRecordCanceled = false;
  615. FileUtil.deleteFile(mOutputPath);
  616. // 隐藏录音框
  617. new Handler().postDelayed(new Runnable() {
  618. @Override
  619. public void run() {
  620. if (mRecordPopupWindow != null && mRecordPopupWindow.isShowing()) {
  621. mRecordPopupWindow.dismiss();
  622. }
  623. }
  624. }, 500);
  625. }
  626. }
  627. /**
  628. * 弹出录音框
  629. */
  630. private void showRecordPopupWindow(STATE state) {
  631. if (mRecordPopupWindow == null) {
  632. View contentView = LayoutInflater.from(ChatActivity.this).inflate(R.layout.popup_chat_record, null);
  633. mRecordPopupWindow = new PopupWindow(contentView, WindowManager.LayoutParams.WRAP_CONTENT,
  634. WindowManager.LayoutParams.WRAP_CONTENT, true);
  635. mRecordPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
  636. }
  637. View view = mRecordPopupWindow.getContentView();
  638. if (view != null) {
  639. RelativeLayout rlRecording = (RelativeLayout) view.findViewById(R.id.popup_recording_container);
  640. ImageView ivRecording = (ImageView) view.findViewById(R.id.popup_record_anim);
  641. // 设置动画
  642. List<Drawable> drawableList = new ArrayList<Drawable>();
  643. drawableList.add(getResources().getDrawable(R.drawable.voice1));
  644. drawableList.add(getResources().getDrawable(R.drawable.voice2));
  645. drawableList.add(getResources().getDrawable(R.drawable.voice3));
  646. drawableList.add(getResources().getDrawable(R.drawable.voice4));
  647. drawableList.add(getResources().getDrawable(R.drawable.voice5));
  648. drawableList.add(getResources().getDrawable(R.drawable.voice6));
  649. AnimationDrawable animationDrawable = Utils.getFrameAnim(drawableList, true, 150);
  650. ivRecording.setImageDrawable(animationDrawable);
  651. ImageView ivCancel = (ImageView) view.findViewById(R.id.popup_cancel_record);
  652. ImageView ivTooShort = (ImageView) view.findViewById(R.id.popup_record_too_short);
  653. TextView tvState = (TextView) view.findViewById(R.id.popup_record_state);
  654. switch (state) {
  655. case RECORDING: // 正在录音
  656. rlRecording.setVisibility(View.VISIBLE);
  657. // 播放动画
  658. animationDrawable.start();
  659. ivCancel.setVisibility(View.GONE);
  660. ivTooShort.setVisibility(View.GONE);
  661. tvState.setText(getString(R.string.slideup_to_cancel));
  662. break;
  663. case CANCELED: // 取消录音
  664. rlRecording.setVisibility(View.GONE);
  665. // 停止动画
  666. if (animationDrawable.isRunning()) {
  667. animationDrawable.stop();
  668. }
  669. ivCancel.setVisibility(View.VISIBLE);
  670. ivTooShort.setVisibility(View.GONE);
  671. tvState.setText(getString(R.string.loose_to_cancel));
  672. break;
  673. case TOO_SHORT:// 录音时间太短
  674. rlRecording.setVisibility(View.GONE);
  675. // 停止动画
  676. if (animationDrawable.isRunning()) {
  677. animationDrawable.stop();
  678. }
  679. ivCancel.setVisibility(View.GONE);
  680. ivTooShort.setVisibility(View.VISIBLE);
  681. tvState.setText(getString(R.string.record_too_short));
  682. break;
  683. }
  684. }
  685. mRecordPopupWindow.showAtLocation(mRecyclerView, Gravity.CENTER, 0, 0);
  686. }
  687. @OnClick({R.id.chat_send_msg, R.id.chat_intercept})
  688. public void onClick(View view) {
  689. switch (view.getId()) {
  690. case R.id.chat_send_msg:// 发送文字消息
  691. mBtnSend.setEnabled(true);
  692. sendTextMessage();
  693. break;
  694. case R.id.chat_intercept:// 支付拦截
  695. //添加好评送会员
  696. if (mIsShowSendVipByPraise) {
  697. ActionSheetDialogNoTitle();
  698. } else {
  699. BuyServiceActivity.toBuyServiceActivity(ChatActivity.this, BuyServiceActivity.INTENT_FROM_INTERCEPT,
  700. IConfigConstant.PAY_TAG_FROM_CHAT, IConfigConstant.PAY_WAY_ALL);
  701. }
  702. break;
  703. }
  704. }
  705. private void ActionSheetDialogNoTitle() {
  706. final String[] stringItems = {getString(R.string.free_use), getString(R.string.buy_vip_service)};
  707. final ActionSheetDialog dialog = new ActionSheetDialog(ChatActivity.this, stringItems, mTvIntercept);
  708. dialog.isTitleShow(false).show();
  709. dialog.setOnOperItemClickL(new OnOperItemClickL() {
  710. @Override
  711. public void onOperItemClick(AdapterView<?> parent, View view, int position, long id) {
  712. if (position == 0) {
  713. DialogUtil.showDoubleBtnDialog(getSupportFragmentManager(), getString(R.string.hour12_vip), getString(R.string.send_vip), getString(R.string.go_good), getString(R.string.cancel), false, new OnDoubleDialogClickListener() {
  714. @Override
  715. public void onPositiveClick(View view) {
  716. Intent intent = new Intent();
  717. intent.setAction(Intent.ACTION_VIEW);
  718. intent.setData(Uri.parse("market://details?id=" + VersionInfoUtil.getPackageName(ChatActivity.this)));
  719. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  720. if (VersionInfoUtil.checkAPKExist(ChatActivity.this, "com.android.vending")) {
  721. // 直接跳转Google商店
  722. intent.setPackage("com.android.vending");
  723. }
  724. startActivity(intent);
  725. }
  726. @Override
  727. public void onNegativeClick(View view) {
  728. }
  729. });
  730. } else if (position == 1) {
  731. BuyServiceActivity.toBuyServiceActivity(ChatActivity.this, BuyServiceActivity.INTENT_FROM_INTERCEPT,
  732. IConfigConstant.PAY_TAG_FROM_CHAT, IConfigConstant.PAY_WAY_ALL);
  733. }
  734. dialog.dismiss();
  735. }
  736. });
  737. }
  738. private void loadMsgList() {
  739. OkHttpUtils.post()
  740. .url(IUrlConstant.URL_GET_CHAT_MSG)
  741. .addHeader("token", PlatformInfoXml.getToken())
  742. .addParams("platformInfo", PlatformInfoXml.getPlatformJsonString())
  743. .addParams("uid", mUserId)
  744. .addParams("isUpdateUnPay", isUpdateUnPay)
  745. .addParams("matcherIsRead", "-1")
  746. .build()
  747. .execute(new Callback<MessageList>() {
  748. @Override
  749. public MessageList parseNetworkResponse(Response response, int id) throws Exception {
  750. String resultJson = response.body().string();
  751. if (!TextUtils.isEmpty(resultJson)) {
  752. return JSON.parseObject(resultJson, MessageList.class);
  753. }
  754. return null;
  755. }
  756. @Override
  757. public void onError(Call call, Exception e, int id) {
  758. stopRefresh(3);
  759. }
  760. @Override
  761. public void onResponse(MessageList response, int id) {
  762. if (response != null) {
  763. // 设置支付拦截
  764. String intercept = response.getShowWriteMsgIntercept();
  765. if (!TextUtils.isEmpty(intercept) && "1".equals(intercept)) {
  766. if(country.equals(getString(R.string.united_states).trim()) || country.equals("America")){
  767. if(!UserInfoXml.getSearchInterceptor()){
  768. // 美国拦截;展示拦截窗口
  769. mTvIntercept.setVisibility(View.VISIBLE);
  770. mIsShowWriteMsgIntercept = true;
  771. mRlChatContainer.setVisibility(View.GONE);
  772. }else{
  773. mIsShowWriteMsgIntercept = true;
  774. mRlChatContainer.setVisibility(View.VISIBLE);
  775. }
  776. }else{
  777. mIsShowWriteMsgIntercept = true;
  778. mRlChatContainer.setVisibility(View.VISIBLE);
  779. }
  780. } else {// 不展示拦截入口
  781. // dialog.dismiss();
  782. mIsShowWriteMsgIntercept = false;
  783. mTvIntercept.setVisibility(View.GONE);
  784. mRlChatContainer.setVisibility(View.VISIBLE);
  785. }
  786. mRlChatBottom.setVisibility(View.VISIBLE);
  787. String isSucceed = response.getIsSucceed();
  788. if (!TextUtils.isEmpty(isSucceed) && "1".equals(isSucceed)) {
  789. if (mChatAdapter != null) {
  790. mChatAdapter.setAvatarUrl(mAvatarUrl);
  791. mChatAdapter.setServerSystemTime(response.getSystemTime());
  792. mChatAdapter.isIntercept(mIsShowWriteMsgIntercept);
  793. mChatAdapter.isShowVoiceLoading(false);
  794. mChatAdapter.isShowVoiceRetry(false);
  795. mChatAdapter.isShowImgLoading(false);
  796. mChatAdapter.isShowImgRetry(false);
  797. List<Message> messageList = response.getListMsg();
  798. if (!Util.isListEmpty(messageList)) {
  799. List<Image> imageList = new ArrayList<Image>();
  800. for (Message message : messageList) {
  801. if (message != null) {
  802. Image image = message.getChatImage();
  803. if (image != null) {
  804. imageList.add(image);
  805. }
  806. }
  807. }
  808. mChatAdapter.setAllImageList(imageList);
  809. mChatAdapter.replaceAll(messageList);
  810. // 滚动到底部
  811. mLinearLayoutManager.scrollToPosition(mLinearLayoutManager.getItemCount() - 1);
  812. }
  813. }
  814. }
  815. // 设置五星好评
  816. if (response.getIsShowSendVipByPraise() != null && response.getIsShowSendVipByPraise().equals("1")) {
  817. mIsShowSendVipByPraise = true;
  818. } else {
  819. mIsShowSendVipByPraise = false;
  820. }
  821. }
  822. stopRefresh(1);
  823. }
  824. });
  825. }
  826. private void stopRefresh(int secs) {
  827. new Handler().postDelayed(new Runnable() {
  828. @Override
  829. public void run() {
  830. if (mAutoSwipeRefresh != null) {
  831. mAutoSwipeRefresh.setRefreshing(false);
  832. }
  833. }
  834. }, secs * 1000);
  835. }
  836. /**
  837. * 发送文字消息
  838. */
  839. private void sendTextMessage() {
  840. OkHttpUtils.post()
  841. .url(IUrlConstant.URL_SEND_TEXT_MSG)
  842. .addHeader("token", PlatformInfoXml.getToken())
  843. .addParams("platformInfo", PlatformInfoXml.getPlatformJsonString())
  844. .addParams("uid", mUserId)
  845. .addParams("writeMsgType", "1")
  846. .addParams("content", mEtInput.getText().toString().trim())
  847. .build()
  848. .execute(new Callback<WriteMsg>() {
  849. @Override
  850. public WriteMsg parseNetworkResponse(Response response, int id) throws Exception {
  851. String resultJson = response.body().string();
  852. if (!TextUtils.isEmpty(resultJson)) {
  853. return JSON.parseObject(resultJson, WriteMsg.class);
  854. }
  855. mBtnSend.setEnabled(true);
  856. return null;
  857. }
  858. @Override
  859. public void onError(Call call, Exception e, int id) {
  860. ToastUtil.showShortToast(ChatActivity.this, getString(R.string.send_fail));
  861. mBtnSend.setEnabled(true);
  862. }
  863. @Override
  864. public void onResponse(WriteMsg response, int id) {
  865. if (response != null) {
  866. String isSucceed = response.getIsSucceed();
  867. if (!TextUtils.isEmpty(isSucceed) && "1".equals(isSucceed)) {
  868. // 重置状态
  869. mEtInput.setText("");
  870. loadMsgList();
  871. // 发送事件,更新聊天列表
  872. EventBus.getDefault().post(new MessageChangedEvent());
  873. } else {
  874. ToastUtil.showShortToast(ChatActivity.this, getString(R.string.send_fail));
  875. }
  876. } else {
  877. ToastUtil.showShortToast(ChatActivity.this, getString(R.string.send_fail));
  878. }
  879. }
  880. });
  881. }
  882. /**
  883. * 发送语音消息
  884. */
  885. private void sendVoiceMsg() {
  886. // 发送语音前显示要发送的图片进度
  887. final Message message = new Message();
  888. if (mChatAdapter != null) {
  889. mChatAdapter.isShowVoiceLoading(true);
  890. mChatAdapter.isShowVoiceRetry(false);
  891. message.setUid(UserInfoXml.getUID());
  892. message.setMsgType("7");
  893. message.setCreateDateMills(System.currentTimeMillis());
  894. message.setRecevStatus("1");
  895. message.setAudioTime(String.valueOf(Math.round(mRecordDuration / 1000)));
  896. message.setAudioUrl(mOutputPath);
  897. mChatAdapter.insertItem(mChatAdapter.getItemCount(), message);
  898. // 滚动到底部
  899. mLinearLayoutManager.scrollToPosition(mChatAdapter.getItemCount() - 1);
  900. }
  901. OkHttpUtils.post()
  902. .url(IUrlConstant.URL_SEND_VOICE_MSG)
  903. .addHeader("token", PlatformInfoXml.getToken())
  904. .addHeader("platformInfo", PlatformInfoXml.getPlatformJsonString())
  905. .addHeader("uid", mUserId)
  906. .addHeader("writeMsgType", "1")
  907. .addHeader("audioSecond", String.valueOf(Math.round(mRecordDuration / 1000)))
  908. .addFile("file", mRecordFileName, new File(mOutputPath))
  909. .build()
  910. .execute(new Callback<BaseModel>() {
  911. @Override
  912. public BaseModel parseNetworkResponse(Response response, int id) throws Exception {
  913. String resultJson = response.body().string();
  914. if (!TextUtils.isEmpty(resultJson)) {
  915. return JSON.parseObject(resultJson, BaseModel.class);
  916. }
  917. return null;
  918. }
  919. @Override
  920. public void onError(Call call, Exception e, int id) {
  921. sendVoiceFailed(message);
  922. }
  923. @Override
  924. public void onResponse(BaseModel response, int id) {
  925. if (response != null) {
  926. String isSucceed = response.getIsSucceed();
  927. if (!TextUtils.isEmpty(isSucceed) && "1".equals(isSucceed)) {
  928. loadMsgList();
  929. // 发送事件,更新聊天列表
  930. EventBus.getDefault().post(new MessageChangedEvent());
  931. } else {
  932. sendVoiceFailed(message);
  933. }
  934. } else {
  935. sendVoiceFailed(message);
  936. }
  937. }
  938. });
  939. }
  940. /**
  941. * 发送语音失败,刷新状态
  942. */
  943. private void sendVoiceFailed(Message message) {
  944. mChatAdapter.isShowVoiceLoading(false);
  945. mChatAdapter.isShowVoiceRetry(true);
  946. mChatAdapter.updateItem(mChatAdapter.getItemCount() - 1, message);
  947. ToastUtil.showShortToast(ChatActivity.this, getString(R.string.send_fail));
  948. }
  949. /**
  950. * 发送图片消息
  951. */
  952. private void sendPhotoMsg(File file, final Message message) {
  953. OkHttpUtils.post()
  954. .url(IUrlConstant.URL_SEND_PHOTO_MSG)
  955. .addHeader("token", PlatformInfoXml.getToken())
  956. .addHeader("platformInfo", PlatformInfoXml.getPlatformJsonString())
  957. .addHeader("recevUserId", mUserId)
  958. .addFile("request", file.getName(), file)
  959. .build()
  960. .execute(new Callback<BaseModel>() {
  961. @Override
  962. public BaseModel parseNetworkResponse(Response response, int id) throws Exception {
  963. String resultJson = response.body().string();
  964. if (!TextUtils.isEmpty(resultJson)) {
  965. return JSON.parseObject(resultJson, BaseModel.class);
  966. }
  967. return null;
  968. }
  969. @Override
  970. public void onError(Call call, Exception e, int id) {
  971. sendPhotoFailed(message);
  972. }
  973. @Override
  974. public void onResponse(BaseModel response, int id) {
  975. if (response != null) {
  976. String isSucceed = response.getIsSucceed();
  977. if (!TextUtils.isEmpty(isSucceed) && "1".equals(isSucceed)) {
  978. loadMsgList();
  979. // 发送事件,更新聊天列表
  980. EventBus.getDefault().post(new MessageChangedEvent());
  981. } else {
  982. sendPhotoFailed(message);
  983. }
  984. } else {
  985. sendPhotoFailed(message);
  986. }
  987. }
  988. });
  989. }
  990. /**
  991. * 发送图片失败,刷新状态
  992. */
  993. private void sendPhotoFailed(Message message) {
  994. mChatAdapter.isShowImgLoading(false);
  995. mChatAdapter.isShowImgRetry(true);
  996. mChatAdapter.updateItem(mChatAdapter.getItemCount() - 1, message);
  997. ToastUtil.showShortToast(ChatActivity.this, getString(R.string.send_fail));
  998. }
  999. @Override
  1000. protected void doRegister() {
  1001. super.doRegister();
  1002. EventBus.getDefault().register(this);
  1003. }
  1004. @Override
  1005. protected void unregister() {
  1006. super.unregister();
  1007. EventBus.getDefault().unregister(this);
  1008. // 释放录音和播放器资源
  1009. RecordUtil.getInstance().releaseRecord();
  1010. if (RecordUtil.getInstance().isPlaying()) {// 如果正在播放语音,需要停止
  1011. RecordUtil.getInstance().stop();
  1012. }
  1013. RecordUtil.getInstance().release();
  1014. }
  1015. @Subscribe
  1016. public void onEvent(RefreshChatEvent event) {
  1017. loadMsgList();
  1018. }
  1019. @Subscribe
  1020. public void onEvent(RefreshChatDialogEvent event) {
  1021. /**加载读信拦截对话框**/
  1022. if(dialog!=null){
  1023. dialog.dismiss();
  1024. }
  1025. boolean showDalog = SharedPreferenceUtil.getBooleanValue(Utils.getContext(), "INTERCEPT_DIALOG", "DIALOG", true);
  1026. if(showDalog){
  1027. isUpdateUnPay="0";
  1028. showDialog();
  1029. }else{
  1030. isUpdateUnPay="1";
  1031. isShowDialog();
  1032. }
  1033. loadMsgList();
  1034. }
  1035. @Override
  1036. protected void onDestroy() {
  1037. super.onDestroy();
  1038. if(dialog!=null){
  1039. dialog.dismiss();
  1040. }
  1041. //
  1042. }
  1043. }