Commit b979c75194cd950ba968a5eedea12f21c5f7f61e

Authored by 谷俊
1 parent 0c0bc784

demo修改为支持3.0版本功能

Showing 62 changed files with 1820 additions and 411 deletions
.idea/misc.xml
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4"> 2 <project version="4">
3 - <component name="EntryPointsManager">  
4 - <entry_points version="2.0" />  
5 - </component>  
6 <component name="NullableNotNullManager"> 3 <component name="NullableNotNullManager">
7 <option name="myDefaultNullable" value="android.support.annotation.Nullable" /> 4 <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
8 <option name="myDefaultNotNull" value="android.support.annotation.NonNull" /> 5 <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
@@ -27,17 +24,7 @@ @@ -27,17 +24,7 @@
27 </value> 24 </value>
28 </option> 25 </option>
29 </component> 26 </component>
30 - <component name="ProjectLevelVcsManager" settingsEditedManually="false">  
31 - <OptionsSetting value="true" id="Add" />  
32 - <OptionsSetting value="true" id="Remove" />  
33 - <OptionsSetting value="true" id="Checkout" />  
34 - <OptionsSetting value="true" id="Update" />  
35 - <OptionsSetting value="true" id="Status" />  
36 - <OptionsSetting value="true" id="Edit" />  
37 - <ConfirmationsSetting value="0" id="Add" />  
38 - <ConfirmationsSetting value="0" id="Remove" />  
39 - </component>  
40 - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> 27 + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
41 <output url="file://$PROJECT_DIR$/build/classes" /> 28 <output url="file://$PROJECT_DIR$/build/classes" />
42 </component> 29 </component>
43 <component name="ProjectType"> 30 <component name="ProjectType">
.idea/modules.xml
@@ -2,12 +2,10 @@ @@ -2,12 +2,10 @@
2 <project version="4"> 2 <project version="4">
3 <component name="ProjectModuleManager"> 3 <component name="ProjectModuleManager">
4 <modules> 4 <modules>
5 - <module fileurl="file://$PROJECT_DIR$/CNChatNDemo.iml" filepath="$PROJECT_DIR$/CNChatNDemo.iml" /> 5 + <module fileurl="file://D:\gitlab\CNIMDemo\CNChatNDemo.iml" filepath="D:\gitlab\CNIMDemo\CNChatNDemo.iml" />
6 <module fileurl="file://$PROJECT_DIR$/CNIMDemo.iml" filepath="$PROJECT_DIR$/CNIMDemo.iml" /> 6 <module fileurl="file://$PROJECT_DIR$/CNIMDemo.iml" filepath="$PROJECT_DIR$/CNIMDemo.iml" />
7 - <module fileurl="file://$PROJECT_DIR$/CNIMDemo.iml" filepath="$PROJECT_DIR$/CNIMDemo.iml" />  
8 - <module fileurl="file://$PROJECT_DIR$/CNIMDemo23.iml" filepath="$PROJECT_DIR$/CNIMDemo23.iml" />  
9 - <module fileurl="file://$PROJECT_DIR$/CNIMDemo5.iml" filepath="$PROJECT_DIR$/CNIMDemo5.iml" />  
10 - <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> 7 + <module fileurl="file://D:\gitlab\CNIMDemo\CNIMDemo23.iml" filepath="D:\gitlab\CNIMDemo\CNIMDemo23.iml" />
  8 + <module fileurl="file://D:\gitlab\CNIMDemo\CNIMDemo5.iml" filepath="D:\gitlab\CNIMDemo\CNIMDemo5.iml" />
11 <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> 9 <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
12 </modules> 10 </modules>
13 </component> 11 </component>
app/build.gradle
@@ -27,11 +27,17 @@ android { @@ -27,11 +27,17 @@ android {
27 minifyEnabled true 27 minifyEnabled true
28 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 28 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 signingConfig signingConfigs.myConfig 29 signingConfig signingConfigs.myConfig
  30 + ndk {
  31 + abiFilters "armeabi-v7a", "arm64-v8a"
  32 + }
30 } 33 }
31 debug { 34 debug {
32 minifyEnabled false 35 minifyEnabled false
33 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 36 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
34 debuggable true 37 debuggable true
  38 + ndk {
  39 + abiFilters "armeabi-v7a", "arm64-v8a"
  40 + }
35 } 41 }
36 } 42 }
37 } 43 }
@@ -46,5 +52,5 @@ dependencies { @@ -46,5 +52,5 @@ dependencies {
46 compile 'com.android.support:recyclerview-v7:23.4.0' 52 compile 'com.android.support:recyclerview-v7:23.4.0'
47 compile 'com.github.bumptech.glide:glide:3.7.0' 53 compile 'com.github.bumptech.glide:glide:3.7.0'
48 54
49 - compile 'com.cnlive:lib_cnutil:2.0.1' 55 +// compile 'com.cnlive:lib_cnutil:2.0.1'
50 } 56 }
app/src/main/AndroidManifest.xml
@@ -2,18 +2,20 @@ @@ -2,18 +2,20 @@
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="com.cnlive.im"> 3 package="com.cnlive.im">
4 4
5 - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
6 - <uses-permission android:name="android.permission.INTERNET" />  
7 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 5 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
8 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 6 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
9 - <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
10 - <uses-permission android:name="android.permission.RECORD_AUDIO" /> 7 + <uses-permission android:name="android.permission.CAMERA" />
  8 + <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
11 <uses-permission android:name="android.permission.GET_TASKS" /> 9 <uses-permission android:name="android.permission.GET_TASKS" />
12 - <uses-permission android:name="android.permission.WAKE_LOCK" /> 10 + <uses-permission android:name="android.permission.INTERNET" />
13 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 11 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
14 - <uses-permission android:name="android.permission.VIBRATE" />  
15 - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 12 + <uses-permission android:name="android.permission.READ_LOGS" />
  13 + <uses-permission android:name="android.permission.READ_PHONE_STATE" />
16 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 14 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  15 + <uses-permission android:name="android.permission.RECORD_AUDIO" />
  16 + <uses-permission android:name="android.permission.VIBRATE" />
  17 + <uses-permission android:name="android.permission.WAKE_LOCK" />
  18 + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
17 19
18 <application 20 <application
19 android:name=".CNLiveApplication" 21 android:name=".CNLiveApplication"
@@ -21,7 +23,7 @@ @@ -21,7 +23,7 @@
21 android:icon="@mipmap/ic_launcher" 23 android:icon="@mipmap/ic_launcher"
22 android:label="@string/app_name" 24 android:label="@string/app_name"
23 android:supportsRtl="true" 25 android:supportsRtl="true"
24 - android:theme="@style/AppTheme"> 26 + android:theme="@style/AppTheme.NoActionBar">
25 <activity android:name=".ui.MainActivity"> 27 <activity android:name=".ui.MainActivity">
26 <intent-filter> 28 <intent-filter>
27 <action android:name="android.intent.action.MAIN" /> 29 <action android:name="android.intent.action.MAIN" />
@@ -46,20 +48,54 @@ @@ -46,20 +48,54 @@
46 <activity android:name=".ui.PrivateActivity" 48 <activity android:name=".ui.PrivateActivity"
47 android:screenOrientation="portrait"/> 49 android:screenOrientation="portrait"/>
48 50
  51 + <activity android:name=".ui.VideoActivity"
  52 + android:screenOrientation="portrait"
  53 + android:launchMode="singleTop"/>
  54 +
  55 + <activity android:name=".ui.ImageViewActivity"
  56 + android:screenOrientation="portrait"
  57 + android:launchMode="singleTop"/>
  58 +
  59 + <!-- 【必须】消息收发service -->
49 <service 60 <service
50 - android:name="io.rong.imlib.ipc.RongService" 61 + android:name="com.tencent.qalsdk.service.QalService"
51 android:exported="true" 62 android:exported="true"
52 - android:process=":ipc" /> 63 + android:process=":QALSERVICE" >
  64 + </service>
53 <service 65 <service
54 - android:name="io.rong.imlib.ReConnectService"  
55 - android:exported="true" /> 66 + android:name="com.tencent.qalsdk.service.QalAssistService"
  67 + android:exported="false"
  68 + android:process=":QALSERVICE" >
  69 + </service>
56 70
  71 + <!-- 【必须】 离线消息广播接收器 -->
57 <receiver 72 <receiver
58 - android:name="io.rong.imlib.ConnectChangeReceiver"  
59 - android:exported="true" /> 73 + android:name="com.tencent.qalsdk.QALBroadcastReceiver"
  74 + android:exported="false">
  75 + <intent-filter>
  76 + <action android:name="com.tencent.qalsdk.broadcast.qal" />
  77 + </intent-filter>
  78 + </receiver>
60 <receiver 79 <receiver
61 - android:name="io.rong.imlib.HeartbeatReceiver"  
62 - android:process=":ipc" /> 80 + android:name="com.tencent.qalsdk.core.NetConnInfoCenter" android:process=":QALSERVICE">
  81 + <intent-filter>
  82 + <action android:name="android.intent.action.BOOT_COMPLETED" />
  83 + </intent-filter>
  84 + <intent-filter>
  85 + <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
  86 + </intent-filter>
  87 + <intent-filter>
  88 + <action android:name="android.intent.action.TIME_SET" />
  89 + </intent-filter>
  90 + <intent-filter>
  91 + <action android:name="android.intent.action.TIMEZONE_CHANGED" />
  92 + </intent-filter>
  93 +
  94 + <!-- ImSDK 3.0.2 后添加 -->
  95 + <intent-filter>
  96 + <action android:name="com.tencent.qalsdk.service.TASK_REMOVED" />
  97 + </intent-filter>
  98 + </receiver>
63 99
64 </application> 100 </application>
65 101
app/src/main/java/com/cnlive/im/CNLiveApplication.java
1 package com.cnlive.im; 1 package com.cnlive.im;
2 2
3 import android.app.Application; 3 import android.app.Application;
  4 +import android.content.Context;
4 5
5 import com.cnlive.libs.util.Config; 6 import com.cnlive.libs.util.Config;
6 7
@@ -11,10 +12,17 @@ import com.cnlive.libs.util.Config; @@ -11,10 +12,17 @@ import com.cnlive.libs.util.Config;
11 * @desc ${TODD} 12 * @desc ${TODD}
12 */ 13 */
13 public class CNLiveApplication extends Application { 14 public class CNLiveApplication extends Application {
  15 + private static Context context;
  16 +
14 @Override 17 @Override
15 public void onCreate() { 18 public void onCreate() {
16 super.onCreate(); 19 super.onCreate();
17 - Config.init(this, "60_j07o9s9b65", "dc1e76f87c7c2d83dcedb8a1204ec22fca3e156b21eb0d",true); 20 + context = getApplicationContext();
  21 + Config.init(this, "60_j07o9s9b65", "dc1e76f87c7c2d83dcedb8a1204ec22fca3e156b21eb0d");
  22 + }
  23 +
  24 + public static Context getContext(){
  25 + return context;
18 } 26 }
19 } 27 }
20 28
app/src/main/java/com/cnlive/im/adapter/ChatRoomAdpter.java
1 package com.cnlive.im.adapter; 1 package com.cnlive.im.adapter;
2 2
3 import android.content.Context; 3 import android.content.Context;
4 -import android.database.Cursor;  
5 import android.graphics.Color; 4 import android.graphics.Color;
6 -import android.net.Uri;  
7 -import android.provider.ContactsContract;  
8 -import android.provider.MediaStore; 5 +import android.graphics.drawable.AnimationDrawable;
9 import android.support.v7.widget.RecyclerView; 6 import android.support.v7.widget.RecyclerView;
10 -import android.util.Log;  
11 import android.view.LayoutInflater; 7 import android.view.LayoutInflater;
12 import android.view.View; 8 import android.view.View;
13 import android.view.ViewGroup; 9 import android.view.ViewGroup;
14 -import android.view.WindowManager;  
15 import android.widget.ImageView; 10 import android.widget.ImageView;
16 -import android.widget.LinearLayout;  
17 import android.widget.TextView; 11 import android.widget.TextView;
18 12
19 import com.bumptech.glide.Glide; 13 import com.bumptech.glide.Glide;
20 import com.cnlive.im.R; 14 import com.cnlive.im.R;
21 import com.cnlive.im.adapter.base.BaseRecyclerAdapter; 15 import com.cnlive.im.adapter.base.BaseRecyclerAdapter;
22 -import com.cnlive.im.adapter.base.VoiceItemClickListener; 16 +import com.cnlive.im.adapter.base.ItemClickListener;
23 import com.cnlive.im.mode.ImagMessage; 17 import com.cnlive.im.mode.ImagMessage;
24 import com.cnlive.im.mode.StringMessage; 18 import com.cnlive.im.mode.StringMessage;
  19 +import com.cnlive.im.mode.VideoMessage;
25 import com.cnlive.im.mode.VoiceMessage; 20 import com.cnlive.im.mode.VoiceMessage;
  21 +import com.cnlive.im.util.FileUtil;
  22 +import com.cnlive.libs.util.chat.base.IChat;
26 23
27 import org.json.JSONException; 24 import org.json.JSONException;
28 import org.json.JSONObject; 25 import org.json.JSONObject;
29 26
30 -import java.text.SimpleDateFormat;  
31 -import java.util.Calendar;  
32 -import java.util.Date;  
33 -import java.util.HashMap;  
34 -import java.util.Locale;  
35 -  
36 /** 27 /**
37 * @author 陈硕 28 * @author 陈硕
38 * @time 2017/7/14 14:35 29 * @time 2017/7/14 14:35
@@ -46,8 +37,10 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -46,8 +37,10 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
46 private int imaOppsite = 4; 37 private int imaOppsite = 4;
47 private int voiceUser = 5; 38 private int voiceUser = 5;
48 private int voiceOppsite = 6; 39 private int voiceOppsite = 6;
  40 + private int videoUser = 7;
  41 + private int videoOppsite = 8;
49 private Context mContext; 42 private Context mContext;
50 - private VoiceItemClickListener mVoiceItemClickListener; 43 + private ItemClickListener mItemClickListener;
51 44
52 private boolean isPrivate; 45 private boolean isPrivate;
53 46
@@ -58,8 +51,8 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -58,8 +51,8 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
58 } 51 }
59 52
60 53
61 - public void setonVoiceItemClickListener(VoiceItemClickListener voiveItemClickListener) {  
62 - this.mVoiceItemClickListener = voiveItemClickListener; 54 + public void setonVoiceItemClickListener(ItemClickListener itemClickListener) {
  55 + this.mItemClickListener = itemClickListener;
63 } 56 }
64 57
65 @Override 58 @Override
@@ -80,6 +73,12 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -80,6 +73,12 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
80 return voiceUser; 73 return voiceUser;
81 else return voiceOppsite; 74 else return voiceOppsite;
82 75
  76 + } else if (o instanceof VideoMessage) {
  77 + VideoMessage o1 = (VideoMessage) o;
  78 + if (o1.isUserSend())
  79 + return videoUser;
  80 + else return videoOppsite;
  81 +
83 } 82 }
84 return 0; 83 return 0;
85 } 84 }
@@ -98,6 +97,10 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -98,6 +97,10 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
98 return new VoiceMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.voice_layout_item_user, null)); 97 return new VoiceMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.voice_layout_item_user, null));
99 } else if (viewType == voiceOppsite) { 98 } else if (viewType == voiceOppsite) {
100 return new VoiceMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.voice_layout_item_oppsite, null)); 99 return new VoiceMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.voice_layout_item_oppsite, null));
  100 + } else if (viewType == videoUser) {
  101 + return new VideoMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.video_layout_item_user, null));
  102 + } else if (viewType == videoOppsite) {
  103 + return new VideoMessageHolder(LayoutInflater.from(mContext).inflate(R.layout.video_layout_item_oppsite, null));
101 } 104 }
102 return null; 105 return null;
103 } 106 }
@@ -108,42 +111,22 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -108,42 +111,22 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
108 StringMessageHolder holder1 = (StringMessageHolder) holder; 111 StringMessageHolder holder1 = (StringMessageHolder) holder;
109 Object o = mItems.get(position); 112 Object o = mItems.get(position);
110 StringMessage o1 = (StringMessage) o; 113 StringMessage o1 = (StringMessage) o;
111 - if (isPrivate) {  
112 - try {  
113 - holder1.msg_text.setText((String) (new JSONObject(o1.getCnMessage().getContent()).get("message")));  
114 - } catch (JSONException e) {  
115 - e.printStackTrace();  
116 - }  
117 - } else {  
118 - holder1.msg_text.setText(o1.getCnMessage().getContent());  
119 - }  
120 - holder1.user_name.setText(o1.getCnMessage().getUserInfo().getUserName());  
121 - holder1.user_name.setTextColor(Color.parseColor("#d61d0c"));  
122 - holder1.msg_text.setTextColor(Color.BLACK); 114 + holder1.showMessage(o1);
123 } else if (holder instanceof ImaMessageHolder) { 115 } else if (holder instanceof ImaMessageHolder) {
124 ImaMessageHolder holder1 = (ImaMessageHolder) holder; 116 ImaMessageHolder holder1 = (ImaMessageHolder) holder;
125 Object o = mItems.get(position); 117 Object o = mItems.get(position);
126 ImagMessage o1 = (ImagMessage) o; 118 ImagMessage o1 = (ImagMessage) o;
127 - holder1.ima_user_name.setTextColor(Color.parseColor("#d61d0c"));  
128 - holder1.img_content.getLayoutParams().height = 200;  
129 - holder1.img_content.getLayoutParams().width = 200;  
130 - holder1.img_content.setLayoutParams(holder1.img_content.getLayoutParams());  
131 - Glide.with(mContext).load(o1.getCnImgMessage().getRemoteUri()).into(holder1.img_content);  
132 - holder1.ima_user_name.setText(o1.getCnImgMessage().getUserInfo().getUserName()); 119 + holder1.showMessage(o1);
133 } else if (holder instanceof VoiceMessageHolder) { 120 } else if (holder instanceof VoiceMessageHolder) {
134 - VoiceMessageHolder holder1 = (VoiceMessageHolder) holder;  
135 - Object o = mItems.get(position);  
136 - VoiceMessage o1 = (VoiceMessage) o;  
137 - holder1.voice_user_name.setText(o1.getCnVoiceMessage().getUserInfo().getUserName());  
138 - final Uri voiceUri = o1.getCnVoiceMessage().getVoiceUri();  
139 - int duration = o1.getCnVoiceMessage().getVoiceTime();  
140 - holder1.voice_duration.setText(String.valueOf(duration).concat("\""));  
141 - holder1.itemView.setOnClickListener(new View.OnClickListener() {  
142 - @Override  
143 - public void onClick(View v) {  
144 - mVoiceItemClickListener.onItemClick(voiceUri);  
145 - }  
146 - }); 121 + final VoiceMessageHolder holder1 = (VoiceMessageHolder) holder;
  122 + final Object o = mItems.get(position);
  123 + final VoiceMessage o1 = (VoiceMessage) o;
  124 + holder1.showMessage(o1);
  125 + } else if (holder instanceof VideoMessageHolder) {
  126 + final VideoMessageHolder holder1 = (VideoMessageHolder) holder;
  127 + final Object o = mItems.get(position);
  128 + final VideoMessage o1 = (VideoMessage) o;
  129 + holder1.showMessage(o1);
147 } 130 }
148 131
149 } 132 }
@@ -151,12 +134,48 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -151,12 +134,48 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
151 public class StringMessageHolder extends RecyclerView.ViewHolder { 134 public class StringMessageHolder extends RecyclerView.ViewHolder {
152 private TextView user_name; 135 private TextView user_name;
153 private TextView msg_text; 136 private TextView msg_text;
  137 + private TextView status;
154 138
155 public StringMessageHolder(View itemView) { 139 public StringMessageHolder(View itemView) {
156 super(itemView); 140 super(itemView);
157 user_name = (TextView) itemView.findViewById(R.id.user_name); 141 user_name = (TextView) itemView.findViewById(R.id.user_name);
158 msg_text = (TextView) itemView.findViewById(R.id.msg_text); 142 msg_text = (TextView) itemView.findViewById(R.id.msg_text);
  143 + status = (TextView) itemView.findViewById(R.id.status);
  144 + }
  145 +
  146 + public void showMessage(StringMessage item) {
  147 + user_name.setText(item.getCnMessage().getUserInfo().getUserName());
159 148
  149 + switch (item.getCnMessage().getStatus()) {
  150 + case IChat.CN_MSG_STATUS_SENDING:
  151 + if (status != null)
  152 + status.setText("发送中");
  153 + sendMsg(item);
  154 + break;
  155 + case IChat.CN_MSG_STATUS_SEND_FAIL:
  156 + if (status != null)
  157 + status.setText("发送失败");
  158 + sendMsg(item);
  159 + break;
  160 + case IChat.CN_MSG_STATUS_SEND_SUCCESS:
  161 + if (status != null)
  162 + status.setText("发送成功");
  163 + sendMsg(item);
  164 + break;
  165 + }
  166 + }
  167 +
  168 + private void sendMsg(StringMessage item) {
  169 + if (isPrivate) {
  170 + try {
  171 + msg_text.setText((String) (new JSONObject(item.getCnMessage().getContent()).get("message")));
  172 + } catch (JSONException e) {
  173 + e.printStackTrace();
  174 + }
  175 + } else {
  176 + msg_text.setText(item.getCnMessage().getContent());
  177 + }
  178 + msg_text.setTextColor(Color.BLACK);
160 } 179 }
161 } 180 }
162 181
@@ -164,11 +183,74 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -164,11 +183,74 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
164 183
165 private TextView ima_user_name; 184 private TextView ima_user_name;
166 private ImageView img_content; 185 private ImageView img_content;
  186 + private TextView status;
167 187
168 public ImaMessageHolder(View itemView) { 188 public ImaMessageHolder(View itemView) {
169 super(itemView); 189 super(itemView);
170 ima_user_name = (TextView) itemView.findViewById(R.id.img_user_name); 190 ima_user_name = (TextView) itemView.findViewById(R.id.img_user_name);
171 img_content = (ImageView) itemView.findViewById(R.id.img_content); 191 img_content = (ImageView) itemView.findViewById(R.id.img_content);
  192 + status = (TextView) itemView.findViewById(R.id.status);
  193 + }
  194 +
  195 + public void showMessage(final ImagMessage imagMessage) {
  196 + ima_user_name.setText(imagMessage.getCnImgMessage().getUserInfo().getUserName());
  197 + img_content.getLayoutParams().height = 200;
  198 + img_content.getLayoutParams().width = 200;
  199 + img_content.setLayoutParams(img_content.getLayoutParams());
  200 + switch (imagMessage.getCnImgMessage().getStatus()) {
  201 + case IChat.CN_MSG_STATUS_SENDING:
  202 + if (status != null)
  203 + status.setText("发送中");
  204 + Glide.with(mContext).load(imagMessage.getCnImgMessage().getImagePath()).into(img_content);
  205 + break;
  206 + case IChat.CN_MSG_STATUS_SEND_FAIL:
  207 + if (status != null)
  208 + status.setText("发送失败");
  209 + Glide.with(mContext).load(imagMessage.getCnImgMessage().getImagePath()).into(img_content);
  210 + break;
  211 + case IChat.CN_MSG_STATUS_SEND_SUCCESS:
  212 + if (status != null)
  213 + status.setText("发送成功");
  214 + sendSuccess(imagMessage);
  215 + break;
  216 + }
  217 + }
  218 +
  219 + private void sendSuccess(final ImagMessage imagMessage) {
  220 + if (imagMessage.getCnImgMessage().isSelf()) {
  221 + Glide.with(mContext).load(imagMessage.getCnImgMessage().getImagePath()).into(img_content);
  222 + } else {
  223 + String thumbUuid = imagMessage.getCnImgMessage().getThumbUuid();
  224 + final String imagePath = FileUtil.getCacheFilePath(thumbUuid);
  225 + if (FileUtil.isCacheFileExist(thumbUuid)) {
  226 + if (img_content != null && mContext != null)
  227 + Glide.with(mContext).load(imagePath).into(img_content);
  228 + } else {
  229 + if (!imagMessage.isDownloading()) {
  230 + imagMessage.setDownloading(true);
  231 + imagMessage.getCnImgMessage().getThumbImage(imagePath, new IChat.OnDownloadListener() {
  232 + @Override
  233 + public void onSuccess() {
  234 + imagMessage.setDownloading(false);
  235 + if (img_content != null && mContext != null)
  236 + Glide.with(mContext).load(imagePath).into(img_content);
  237 + }
  238 +
  239 + @Override
  240 + public void onError(int i, String s) {
  241 + imagMessage.setDownloading(false);
  242 + }
  243 + });
  244 + }
  245 + }
  246 + }
  247 + img_content.setOnClickListener(new View.OnClickListener() {
  248 + @Override
  249 + public void onClick(View v) {
  250 + if (mItemClickListener != null)
  251 + mItemClickListener.onImageClick(imagMessage);
  252 + }
  253 + });
172 } 254 }
173 } 255 }
174 256
@@ -176,14 +258,127 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter { @@ -176,14 +258,127 @@ public class ChatRoomAdpter extends BaseRecyclerAdapter {
176 258
177 259
178 private TextView voice_user_name; 260 private TextView voice_user_name;
179 - private TextView voice_content; 261 + private ImageView voiceAnim;
180 private TextView voice_duration; 262 private TextView voice_duration;
  263 + private View voice_none_read;
  264 + private TextView status;
181 265
182 public VoiceMessageHolder(View itemView) { 266 public VoiceMessageHolder(View itemView) {
183 super(itemView); 267 super(itemView);
184 voice_user_name = (TextView) itemView.findViewById(R.id.voice_user_name); 268 voice_user_name = (TextView) itemView.findViewById(R.id.voice_user_name);
185 - voice_content = (TextView) itemView.findViewById(R.id.voice_content); 269 + voiceAnim = (ImageView) itemView.findViewById(R.id.voiceAnim);
186 voice_duration = (TextView) itemView.findViewById(R.id.voice_duration); 270 voice_duration = (TextView) itemView.findViewById(R.id.voice_duration);
  271 + voice_none_read = itemView.findViewById(R.id.noneRead);
  272 + status = (TextView) itemView.findViewById(R.id.status);
  273 + }
  274 +
  275 + public void showMessage(final VoiceMessage voiceMessage) {
  276 + voice_user_name.setText(voiceMessage.getCnVoiceMessage().getUserInfo().getUserName());
  277 + int duration = voiceMessage.getCnVoiceMessage().getVoiceTime();
  278 + voice_duration.setText(String.valueOf(duration).concat("\""));
  279 + switch (voiceMessage.getCnVoiceMessage().getStatus()) {
  280 + case IChat.CN_MSG_STATUS_SENDING:
  281 + if (status != null)
  282 + status.setText("发送中");
  283 + break;
  284 + case IChat.CN_MSG_STATUS_SEND_FAIL:
  285 + if (status != null)
  286 + status.setText("发送失败");
  287 + break;
  288 + case IChat.CN_MSG_STATUS_SEND_SUCCESS:
  289 + if (status != null)
  290 + status.setText("发送成功");
  291 + sendSuccess(voiceMessage);
  292 + break;
  293 + }
  294 + }
  295 +
  296 + private void sendSuccess(final VoiceMessage voiceMessage) {
  297 + if (voice_none_read != null)
  298 + voice_none_read.setVisibility(voiceMessage.getCnVoiceMessage().isRead() ? View.GONE : View.VISIBLE);
  299 + itemView.setOnClickListener(new View.OnClickListener() {
  300 + @Override
  301 + public void onClick(View v) {
  302 + if (mItemClickListener != null)
  303 + mItemClickListener.onItemClick(voiceMessage, (AnimationDrawable) voiceAnim.getBackground());
  304 + if (voice_none_read != null)
  305 + voice_none_read.setVisibility(View.GONE);
  306 + }
  307 + });
  308 + }
  309 + }
  310 +
  311 + public class VideoMessageHolder extends RecyclerView.ViewHolder {
  312 +
  313 + private TextView video_user_name;
  314 + private ImageView video_snapshot;
  315 + private View videoLayout;
  316 + private TextView status;
  317 +
  318 + public VideoMessageHolder(View itemView) {
  319 + super(itemView);
  320 + video_user_name = (TextView) itemView.findViewById(R.id.user_name);
  321 + video_snapshot = (ImageView) itemView.findViewById(R.id.img_content);
  322 + videoLayout = itemView.findViewById(R.id.videoLayout);
  323 + status = (TextView) itemView.findViewById(R.id.status);
  324 + }
  325 +
  326 + public void showMessage(final VideoMessage videoMessage) {
  327 + video_user_name.setText(videoMessage.getCnVideoMessage().getUserInfo().getUserName());
  328 + switch (videoMessage.getCnVideoMessage().getStatus()) {
  329 + case IChat.CN_MSG_STATUS_SENDING:
  330 + if (status != null)
  331 + status.setText("发送中");
  332 + Glide.with(mContext).load(videoMessage.getCnVideoMessage().getSnapshotPath()).into(video_snapshot);
  333 + break;
  334 + case IChat.CN_MSG_STATUS_SEND_FAIL:
  335 + if (status != null)
  336 + status.setText("发送失败");
  337 + Glide.with(mContext).load(videoMessage.getCnVideoMessage().getSnapshotPath()).into(video_snapshot);
  338 + break;
  339 + case IChat.CN_MSG_STATUS_SEND_SUCCESS:
  340 + if (status != null)
  341 + status.setText("发送成功");
  342 + sendSuccess(videoMessage);
  343 + break;
  344 + }
  345 + }
  346 +
  347 + private void sendSuccess(final VideoMessage videoMessage) {
  348 + videoLayout.setOnClickListener(new View.OnClickListener() {
  349 + @Override
  350 + public void onClick(View v) {
  351 + if (mItemClickListener != null)
  352 + mItemClickListener.onVideoClick(videoMessage);
  353 + }
  354 + });
  355 + if (videoMessage.getCnVideoMessage().isSelf()) {
  356 + Glide.with(mContext).load(videoMessage.getCnVideoMessage().getSnapshotPath()).into(video_snapshot);
  357 + } else {
  358 + String snapshotUuid = videoMessage.getCnVideoMessage().getSnapshot().getUuid();
  359 + final String imagePath = FileUtil.getCacheFilePath(snapshotUuid);
  360 + if (FileUtil.isCacheFileExist(snapshotUuid)) {
  361 + if (video_snapshot != null && mContext != null)
  362 + Glide.with(mContext).load(imagePath).into(video_snapshot);
  363 + } else {
  364 + if (!videoMessage.isDownloading()) {
  365 + videoMessage.setDownloading(true);
  366 + videoMessage.getCnVideoMessage().getSnapshot().getImage(imagePath, new IChat.OnDownloadListener() {
  367 + @Override
  368 + public void onSuccess() {
  369 + videoMessage.setDownloading(false);
  370 + if (video_snapshot != null && mContext != null)
  371 + Glide.with(mContext).load(imagePath).into(video_snapshot);
  372 + }
  373 +
  374 + @Override
  375 + public void onError(int i, String s) {
  376 + videoMessage.setDownloading(false);
  377 + }
  378 + });
  379 + }
  380 + }
  381 + }
187 } 382 }
188 } 383 }
189 384
app/src/main/java/com/cnlive/im/adapter/CommentAdapter.java
@@ -10,7 +10,7 @@ import android.widget.TextView; @@ -10,7 +10,7 @@ import android.widget.TextView;
10 10
11 import com.bumptech.glide.Glide; 11 import com.bumptech.glide.Glide;
12 import com.cnlive.im.R; 12 import com.cnlive.im.R;
13 -import com.cnlive.libs.util.model.CommentItem; 13 +import com.cnlive.libs.util.comment.model.CommentItem;
14 14
15 import java.util.ArrayList; 15 import java.util.ArrayList;
16 import java.util.List; 16 import java.util.List;
app/src/main/java/com/cnlive/im/adapter/base/VoiceItemClickListener.java renamed to app/src/main/java/com/cnlive/im/adapter/base/ItemClickListener.java
1 package com.cnlive.im.adapter.base; 1 package com.cnlive.im.adapter.base;
2 2
3 -import android.net.Uri; 3 +import android.graphics.drawable.AnimationDrawable;
  4 +
  5 +import com.cnlive.im.mode.ImagMessage;
  6 +import com.cnlive.im.mode.VideoMessage;
  7 +import com.cnlive.im.mode.VoiceMessage;
4 8
5 /** 9 /**
6 * @author 陈硕 10 * @author 陈硕
7 * @time 2017/7/14 17:50 11 * @time 2017/7/14 17:50
8 * @desc ${TODD} 12 * @desc ${TODD}
9 */ 13 */
10 -public interface VoiceItemClickListener {  
11 - void onItemClick(Uri uri); 14 +public interface ItemClickListener {
  15 + void onItemClick(VoiceMessage voiceMessage, AnimationDrawable animationDrawable);
  16 +
  17 + void onVideoClick(VideoMessage videoMessage);
  18 +
  19 + void onImageClick(ImagMessage imagMessage);
12 } 20 }
app/src/main/java/com/cnlive/im/mode/ImagMessage.java
@@ -12,6 +12,8 @@ public class ImagMessage { @@ -12,6 +12,8 @@ public class ImagMessage {
12 private CNImgMessage cnImgMessage; 12 private CNImgMessage cnImgMessage;
13 boolean isUserSend; 13 boolean isUserSend;
14 14
  15 + private boolean isDownloading = false;
  16 +
15 17
16 public String getType() { 18 public String getType() {
17 return type; 19 return type;
@@ -37,7 +39,15 @@ public class ImagMessage { @@ -37,7 +39,15 @@ public class ImagMessage {
37 isUserSend = userSend; 39 isUserSend = userSend;
38 } 40 }
39 41
40 - public ImagMessage( String type,CNImgMessage cnImgMessage, boolean isUserSend) { 42 + public boolean isDownloading() {
  43 + return isDownloading;
  44 + }
  45 +
  46 + public void setDownloading(boolean downloading) {
  47 + isDownloading = downloading;
  48 + }
  49 +
  50 + public ImagMessage(String type, CNImgMessage cnImgMessage, boolean isUserSend) {
41 this.type = type; 51 this.type = type;
42 this.cnImgMessage = cnImgMessage; 52 this.cnImgMessage = cnImgMessage;
43 this.isUserSend = isUserSend; 53 this.isUserSend = isUserSend;
app/src/main/java/com/cnlive/im/mode/UgcVideoMessage.java 0 → 100644
  1 +package com.cnlive.im.mode;
  2 +
  3 +import com.cnlive.libs.util.chat.model.CNUgcMessage;
  4 +
  5 +/**
  6 + * Created by gujun on 2017/12/19.
  7 + */
  8 +
  9 +public class UgcVideoMessage {
  10 + private String type;
  11 + private CNUgcMessage cnUgcMessage;
  12 + boolean isUserSend;
  13 +
  14 + private boolean isDownloading = false;
  15 +
  16 + public UgcVideoMessage(String type, CNUgcMessage cnUgcMessage, boolean isUserSend) {
  17 + this.type = type;
  18 + this.cnUgcMessage = cnUgcMessage;
  19 + this.isUserSend = isUserSend;
  20 + }
  21 +
  22 + public String getType() {
  23 + return type;
  24 + }
  25 +
  26 + public void setType(String type) {
  27 + this.type = type;
  28 + }
  29 +
  30 + public CNUgcMessage getCnUgcMessage() {
  31 + return cnUgcMessage;
  32 + }
  33 +
  34 + public void setCnUgcMessage(CNUgcMessage cnUgcMessage) {
  35 + this.cnUgcMessage = cnUgcMessage;
  36 + }
  37 +
  38 + public boolean isUserSend() {
  39 + return isUserSend;
  40 + }
  41 +
  42 + public void setUserSend(boolean userSend) {
  43 + isUserSend = userSend;
  44 + }
  45 +
  46 + public boolean isDownloading() {
  47 + return isDownloading;
  48 + }
  49 +
  50 + public void setDownloading(boolean downloading) {
  51 + isDownloading = downloading;
  52 + }
  53 +}
  54 +
app/src/main/java/com/cnlive/im/mode/VideoMessage.java 0 → 100644
  1 +package com.cnlive.im.mode;
  2 +
  3 +import com.cnlive.libs.util.chat.model.CNVideoMessage;
  4 +
  5 +/**
  6 + * @author 陈硕
  7 + * @time 2017/7/14 16:51
  8 + * @desc ${TODD}
  9 + */
  10 +public class VideoMessage {
  11 + private String type;
  12 + private CNVideoMessage cnVideoMessage;
  13 + boolean isUserSend;
  14 +
  15 + private boolean isDownloading = false;
  16 +
  17 + public VideoMessage(String type, CNVideoMessage cnVideoMessage, boolean isUserSend) {
  18 + this.type = type;
  19 + this.cnVideoMessage = cnVideoMessage;
  20 + this.isUserSend = isUserSend;
  21 + }
  22 +
  23 + public String getType() {
  24 + return type;
  25 + }
  26 +
  27 + public void setType(String type) {
  28 + this.type = type;
  29 + }
  30 +
  31 + public CNVideoMessage getCnVideoMessage() {
  32 + return cnVideoMessage;
  33 + }
  34 +
  35 + public void setCnVideoMessage(CNVideoMessage cnVideoMessage) {
  36 + this.cnVideoMessage = cnVideoMessage;
  37 + }
  38 +
  39 + public boolean isUserSend() {
  40 + return isUserSend;
  41 + }
  42 +
  43 + public void setUserSend(boolean userSend) {
  44 + isUserSend = userSend;
  45 + }
  46 +
  47 + public boolean isDownloading() {
  48 + return isDownloading;
  49 + }
  50 +
  51 + public void setDownloading(boolean downloading) {
  52 + isDownloading = downloading;
  53 + }
  54 +}
app/src/main/java/com/cnlive/im/receiver/CNPushMessageReceiver.java
1 -package com.cnlive.im.receiver;  
2 -  
3 -import android.content.Context;  
4 -  
5 -import com.cnlive.libs.util.chat.model.CNNotificationMessage;  
6 -import com.cnlive.libs.util.chat.receiver.SealNotificationReceiver;  
7 -  
8 -  
9 -/**  
10 - * Created by Lynn on 2/17/2017.  
11 - */  
12 -  
13 -public class CNPushMessageReceiver extends SealNotificationReceiver {  
14 -  
15 - @Override  
16 - public boolean onNotificationMessageArrived(Context var1, CNNotificationMessage var2) {  
17 - //返回false,会弹出SDK默认的通知;返回true,SDK不会弹出通知,通知需要您自定义  
18 - return false;  
19 - }  
20 -  
21 - @Override  
22 - public boolean onNotificationMessageClicked(Context var1, CNNotificationMessage var2) {  
23 - //返回false,会走SDK默认的处理逻辑,即点击该通知则会打开会话列表或会话界面;返回true,则由您自定义处理逻辑  
24 - return false;  
25 - }  
26 -} 1 +//package com.cnlive.im.receiver;
  2 +//
  3 +//import android.content.Context;
  4 +//
  5 +//import com.cnlive.libs.util.chat.model.CNNotificationMessage;
  6 +//import com.cnlive.libs.util.chat.receiver.SealNotificationReceiver;
  7 +//
  8 +//
  9 +///**
  10 +// * Created by Lynn on 2/17/2017.
  11 +// */
  12 +//
  13 +//public class CNPushMessageReceiver extends SealNotificationReceiver {
  14 +//
  15 +// @Override
  16 +// public boolean onNotificationMessageArrived(Context var1, CNNotificationMessage var2) {
  17 +// //返回false,会弹出SDK默认的通知;返回true,SDK不会弹出通知,通知需要您自定义
  18 +// return false;
  19 +// }
  20 +//
  21 +// @Override
  22 +// public boolean onNotificationMessageClicked(Context var1, CNNotificationMessage var2) {
  23 +// //返回false,会走SDK默认的处理逻辑,即点击该通知则会打开会话列表或会话界面;返回true,则由您自定义处理逻辑
  24 +// return false;
  25 +// }
  26 +//}
app/src/main/java/com/cnlive/im/ui/ChatRoomActivity.java
@@ -5,10 +5,14 @@ import android.app.Activity; @@ -5,10 +5,14 @@ import android.app.Activity;
5 import android.content.Context; 5 import android.content.Context;
6 import android.content.Intent; 6 import android.content.Intent;
7 import android.content.pm.PackageManager; 7 import android.content.pm.PackageManager;
  8 +import android.graphics.Bitmap;
  9 +import android.graphics.drawable.AnimationDrawable;
  10 +import android.media.ThumbnailUtils;
8 import android.net.Uri; 11 import android.net.Uri;
9 import android.os.Build; 12 import android.os.Build;
10 import android.os.Bundle; 13 import android.os.Bundle;
11 import android.os.Handler; 14 import android.os.Handler;
  15 +import android.provider.MediaStore;
12 import android.support.annotation.NonNull; 16 import android.support.annotation.NonNull;
13 import android.support.v4.app.ActivityCompat; 17 import android.support.v4.app.ActivityCompat;
14 import android.support.v4.content.ContextCompat; 18 import android.support.v4.content.ContextCompat;
@@ -33,24 +37,28 @@ import android.widget.Toast; @@ -33,24 +37,28 @@ import android.widget.Toast;
33 37
34 import com.cnlive.im.R; 38 import com.cnlive.im.R;
35 import com.cnlive.im.adapter.ChatRoomAdpter; 39 import com.cnlive.im.adapter.ChatRoomAdpter;
36 -import com.cnlive.im.adapter.base.VoiceItemClickListener; 40 +import com.cnlive.im.adapter.base.ItemClickListener;
37 import com.cnlive.im.mode.ImagMessage; 41 import com.cnlive.im.mode.ImagMessage;
38 import com.cnlive.im.mode.StringMessage; 42 import com.cnlive.im.mode.StringMessage;
  43 +import com.cnlive.im.mode.VideoMessage;
39 import com.cnlive.im.mode.VoiceMessage; 44 import com.cnlive.im.mode.VoiceMessage;
40 import com.cnlive.im.util.AudioRecordUtil; 45 import com.cnlive.im.util.AudioRecordUtil;
  46 +import com.cnlive.im.util.FileUtil;
  47 +import com.cnlive.im.util.MediaUtil;
41 import com.cnlive.im.util.MessageType; 48 import com.cnlive.im.util.MessageType;
42 -import com.cnlive.im.util.PlayerUtil;  
43 import com.cnlive.im.util.TimeUtils; 49 import com.cnlive.im.util.TimeUtils;
44 import com.cnlive.im.util.UploadImageUtils; 50 import com.cnlive.im.util.UploadImageUtils;
45 import com.cnlive.libs.util.chat.ChatUtil; 51 import com.cnlive.libs.util.chat.ChatUtil;
46 import com.cnlive.libs.util.chat.base.IChat; 52 import com.cnlive.libs.util.chat.base.IChat;
  53 +import com.cnlive.libs.util.chat.model.CNBaseMessage;
47 import com.cnlive.libs.util.chat.model.CNImgMessage; 54 import com.cnlive.libs.util.chat.model.CNImgMessage;
48 import com.cnlive.libs.util.chat.model.CNMessage; 55 import com.cnlive.libs.util.chat.model.CNMessage;
49 import com.cnlive.libs.util.chat.model.CNUserInfo; 56 import com.cnlive.libs.util.chat.model.CNUserInfo;
  57 +import com.cnlive.libs.util.chat.model.CNVideoMessage;
50 import com.cnlive.libs.util.chat.model.CNVoiceMessage; 58 import com.cnlive.libs.util.chat.model.CNVoiceMessage;
51 59
52 -import org.json.JSONException;  
53 - 60 +import java.io.File;
  61 +import java.io.FileInputStream;
54 import java.util.ArrayList; 62 import java.util.ArrayList;
55 63
56 64
@@ -59,10 +67,13 @@ import java.util.ArrayList; @@ -59,10 +67,13 @@ import java.util.ArrayList;
59 * @time 2017/3/7 14:36 67 * @time 2017/3/7 14:36
60 * @desc ${TODD} 68 * @desc ${TODD}
61 */ 69 */
62 -public class ChatRoomActivity extends AppCompatActivity implements View.OnClickListener, VoiceItemClickListener { 70 +public class ChatRoomActivity extends AppCompatActivity implements View.OnClickListener, ItemClickListener {
63 private static final String TAG = "ChatRoomActivity"; 71 private static final String TAG = "ChatRoomActivity";
64 - private ArrayList<Object> groupChatOneListMy;  
65 - private String roomIdOne = "ChatRoom05"; 72 +
  73 + private final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 0x2001;
  74 +
  75 + private ArrayList<String> groupChatOneListMy;
  76 + private String roomIdOne = "ChatRoom10";
66 private EditText editText; 77 private EditText editText;
67 private Button send_messageOneBtn; 78 private Button send_messageOneBtn;
68 private RecyclerView listViewOne; 79 private RecyclerView listViewOne;
@@ -70,7 +81,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -70,7 +81,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
70 private Button foundChatBtn; 81 private Button foundChatBtn;
71 private Handler mHandler; 82 private Handler mHandler;
72 private RelativeLayout re_chat; 83 private RelativeLayout re_chat;
73 -// private LinearLayout lin_user; 84 + // private LinearLayout lin_user;
74 // private EditText user_id, user_name; 85 // private EditText user_id, user_name;
75 private Button exit_chat1; 86 private Button exit_chat1;
76 public static String user_name_string; 87 public static String user_name_string;
@@ -100,8 +111,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -100,8 +111,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
100 111
101 private String mFilePath; 112 private String mFilePath;
102 113
103 - private PlayerUtil playerUtil;  
104 -  
105 // 所需的全部权限 114 // 所需的全部权限
106 static final String[] PERMISSIONS = new String[]{ 115 static final String[] PERMISSIONS = new String[]{
107 Manifest.permission.RECORD_AUDIO, 116 Manifest.permission.RECORD_AUDIO,
@@ -130,7 +139,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -130,7 +139,6 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
130 ChatUtil.login(new CNUserInfo(user_id_string, user_name_string, ""), connectListener); 139 ChatUtil.login(new CNUserInfo(user_id_string, user_name_string, ""), connectListener);
131 else ChatUtil.logOut(connectListener); 140 else ChatUtil.logOut(connectListener);
132 requestPermission(); 141 requestPermission();
133 - playerUtil = new PlayerUtil(this);  
134 142
135 } 143 }
136 144
@@ -169,6 +177,9 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -169,6 +177,9 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
169 keybordBtn = (ImageView) findViewById(R.id.keybord); 177 keybordBtn = (ImageView) findViewById(R.id.keybord);
170 keybordBtn.setOnClickListener(this); 178 keybordBtn.setOnClickListener(this);
171 179
  180 + findViewById(R.id.videoBtn).setOnClickListener(this);
  181 + findViewById(R.id.ugcVideoBtn).setOnClickListener(this);
  182 +
172 183
173 StartListener(); 184 StartListener();
174 185
@@ -181,43 +192,21 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -181,43 +192,21 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
181 */ 192 */
182 private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() { 193 private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() {
183 @Override 194 @Override
184 - public void onAttached(Object o) {  
185 - 195 + public void onAttached(CNBaseMessage o) {
  196 + showMessage(o);
186 } 197 }
187 198
188 @Override 199 @Override
189 - public void onSuccess(final Object o) throws JSONException {  
190 - mHandler.post(new Runnable() {  
191 - @Override  
192 - public void run() {  
193 - if (o instanceof CNMessage) {  
194 - CNMessage o1 = (CNMessage) o;  
195 - chatListAdapterOne.addItem(new StringMessage(MessageType.stringMessage, o1, true));  
196 - } else if (o instanceof CNImgMessage) {  
197 - CNImgMessage o1 = (CNImgMessage) o;  
198 - chatListAdapterOne.addItem(new ImagMessage(MessageType.imaMessage, o1, true));  
199 - } else if (o instanceof CNVoiceMessage) {  
200 - CNVoiceMessage o1 = (CNVoiceMessage) o;  
201 - VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, true);  
202 - chatListAdapterOne.addItem(voiceMessage);  
203 - //发送成功后删除保存在本地的录制文件  
204 - mAudioRecordUtil.deleteRecordFile(mFilePath);  
205 -  
206 - }  
207 - listViewOne.smoothScrollToPosition(chatListAdapterOne.getItemCount() - 1);  
208 - }  
209 - }); 200 + public void onSuccess(final CNBaseMessage o) {
  201 + updateItem(o);
210 } 202 }
211 203
212 @Override 204 @Override
213 - public void onError(Object o, int i, String s) {  
214 - if (o instanceof CNImgMessage) {  
215 -  
216 - } 205 + public void onError(CNBaseMessage o, int i, String s) {
  206 + updateItem(o);
217 } 207 }
218 }; 208 };
219 209
220 -  
221 //连接状态监听 210 //连接状态监听
222 private IChat.OnConnectStatusListener connectStatusListener = new IChat.OnConnectStatusListener() { 211 private IChat.OnConnectStatusListener connectStatusListener = new IChat.OnConnectStatusListener() {
223 @Override 212 @Override
@@ -229,28 +218,59 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -229,28 +218,59 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
229 218
230 private IChat.OnReceiveMessageListener receiveMessageListener = new IChat.OnReceiveMessageListener() { 219 private IChat.OnReceiveMessageListener receiveMessageListener = new IChat.OnReceiveMessageListener() {
231 @Override 220 @Override
232 - public void processMessage(final Object o) {  
233 - mHandler.post(new Runnable() {  
234 - @Override  
235 - public void run() {  
236 - if (o instanceof CNMessage) {  
237 - CNMessage o1 = (CNMessage) o;  
238 - chatListAdapterOne.addItem(new StringMessage(MessageType.stringMessage, o1, false));  
239 - } else if (o instanceof CNImgMessage) {  
240 - CNImgMessage o1 = (CNImgMessage) o;  
241 - chatListAdapterOne.addItem(new ImagMessage(MessageType.imaMessage, o1, false));  
242 - } else if (o instanceof CNVoiceMessage) {  
243 - CNVoiceMessage o1 = (CNVoiceMessage) o;  
244 - VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, false);  
245 - chatListAdapterOne.addItem(voiceMessage);  
246 - }  
247 - listViewOne.smoothScrollToPosition(chatListAdapterOne.getItemCount() - 1);  
248 - }  
249 - });  
250 - 221 + public void processMessage(final CNBaseMessage o) {
  222 + showMessage(o);
251 } 223 }
252 }; 224 };
253 225
  226 + /**
  227 + * 更新消息
  228 + */
  229 + public void updateItem(CNBaseMessage o) {
  230 + int updateIndex = groupChatOneListMy.indexOf(o.getMessageId());
  231 + if (updateIndex < 0 || chatListAdapterOne.getItemCount() <= 0) return;
  232 + if (o.getMsgType() == IChat.CN_MSG_TYPE_TEXT) {
  233 + CNMessage o1 = (CNMessage) o;
  234 + chatListAdapterOne.updateItem(new StringMessage(MessageType.stringMessage, o1, o1.isSelf()), updateIndex);
  235 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_IMAGE) {
  236 + CNImgMessage o1 = (CNImgMessage) o;
  237 + chatListAdapterOne.updateItem(new ImagMessage(MessageType.imaMessage, o1, o1.isSelf()), updateIndex);
  238 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VOICE) {
  239 + CNVoiceMessage o1 = (CNVoiceMessage) o;
  240 + VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, o1.isSelf());
  241 + chatListAdapterOne.updateItem(voiceMessage, updateIndex);
  242 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VIDEO) {
  243 + CNVideoMessage ol = (CNVideoMessage) o;
  244 + VideoMessage videoMessage = new VideoMessage(MessageType.videoMessage, ol, ol.isSelf());
  245 + chatListAdapterOne.updateItem(videoMessage, updateIndex);
  246 + }
  247 + }
  248 +
  249 + /**
  250 + * 展示消息
  251 + *
  252 + * @param o
  253 + */
  254 + private void showMessage(CNBaseMessage o) {
  255 + groupChatOneListMy.add(o.getMessageId());
  256 + if (o.getMsgType() == IChat.CN_MSG_TYPE_TEXT) {
  257 + CNMessage o1 = (CNMessage) o;
  258 + chatListAdapterOne.addItem(new StringMessage(MessageType.stringMessage, o1, o1.isSelf()));
  259 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_IMAGE) {
  260 + CNImgMessage o1 = (CNImgMessage) o;
  261 + chatListAdapterOne.addItem(new ImagMessage(MessageType.imaMessage, o1, o1.isSelf()));
  262 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VOICE) {
  263 + CNVoiceMessage o1 = (CNVoiceMessage) o;
  264 + VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, o1.isSelf());
  265 + chatListAdapterOne.addItem(voiceMessage);
  266 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VIDEO) {
  267 + CNVideoMessage ol = (CNVideoMessage) o;
  268 + VideoMessage videoMessage = new VideoMessage(MessageType.videoMessage, ol, ol.isSelf());
  269 + chatListAdapterOne.addItem(videoMessage);
  270 + }
  271 + listViewOne.smoothScrollToPosition(chatListAdapterOne.getItemCount() - 1);
  272 + }
  273 +
254 274
255 //聊天室操作 275 //聊天室操作
256 private IChat.OnChatRoomActionListener chatRoomActionListener = new IChat.OnChatRoomActionListener() { 276 private IChat.OnChatRoomActionListener chatRoomActionListener = new IChat.OnChatRoomActionListener() {
@@ -333,7 +353,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -333,7 +353,7 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
333 } 353 }
334 break; 354 break;
335 case R.id.creatChat: 355 case R.id.creatChat:
336 - ChatUtil.joinChatRoom(roomIdOne, 20, onOperationListener); 356 + ChatUtil.joinChatRoom(roomIdOne, -1, onOperationListener);
337 break; 357 break;
338 case R.id.exit_chat1: 358 case R.id.exit_chat1:
339 ChatUtil.quitChatRoom(roomIdOne, onOperationListener); 359 ChatUtil.quitChatRoom(roomIdOne, onOperationListener);
@@ -356,9 +376,30 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -356,9 +376,30 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
356 isVoiceBtnVisible = false; 376 isVoiceBtnVisible = false;
357 } 377 }
358 break; 378 break;
  379 + case R.id.videoBtn:
  380 + openSystemRecorder();
  381 + break;
  382 + case R.id.ugcVideoBtn:
  383 +
  384 + break;
359 } 385 }
360 } 386 }
361 387
  388 + private void openSystemRecorder() {
  389 + // 创建拍照Intent并将控制权返回给调用的程序
  390 + Intent intent = new Intent();
  391 + intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
  392 + intent.addCategory(Intent.CATEGORY_DEFAULT);
  393 +
  394 + // 保存录像到指定的路径
  395 + File file = new File("/sdcard/video.mp4");
  396 + Uri uri = Uri.fromFile(file);
  397 + intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
  398 +
  399 + // 启动图像捕获Intent
  400 + startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
  401 + }
  402 +
362 403
363 public void fromPicture() { 404 public void fromPicture() {
364 if (Build.VERSION.SDK_INT >= 23) { 405 if (Build.VERSION.SDK_INT >= 23) {
@@ -394,7 +435,12 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -394,7 +435,12 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
394 Uri uri = Uri.parse("file://" + picturePath); 435 Uri uri = Uri.parse("file://" + picturePath);
395 ChatUtil.sendImaMessage(IChat.CHATROOM, roomIdOne, uri, uri, sendMessageListener); 436 ChatUtil.sendImaMessage(IChat.CHATROOM, roomIdOne, uri, uri, sendMessageListener);
396 break; 437 break;
397 - 438 + case CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE:
  439 + String videoPath = data.getData().getPath();
  440 + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND);
  441 + String imgPath = FileUtil.createFile(bitmap, System.currentTimeMillis() + "");
  442 + ChatUtil.sendVideoMessage(IChat.CHATROOM, roomIdOne, videoPath, imgPath, MediaUtil.getInstance().getDuration(videoPath), sendMessageListener);
  443 + break;
398 default: 444 default:
399 break; 445 break;
400 } 446 }
@@ -425,11 +471,137 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -425,11 +471,137 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
425 } 471 }
426 }; 472 };
427 473
  474 + /**
  475 + * 播放语音文件
  476 + *
  477 + * @param voicePath
  478 + * @param animationDrawable
  479 + */
  480 + private void startVoice(String voicePath, final AnimationDrawable animationDrawable) {
  481 + try {
  482 + FileInputStream fis = new FileInputStream(voicePath);
  483 + MediaUtil.getInstance().play(fis);
  484 + animationDrawable.start();
  485 + MediaUtil.getInstance().setEventListener(new MediaUtil.EventListener() {
  486 + @Override
  487 + public void onStop() {
  488 + animationDrawable.stop();
  489 + animationDrawable.selectDrawable(0);
  490 + }
  491 + });
  492 + } catch (Exception e) {
  493 + }
  494 + }
428 495
429 @Override 496 @Override
430 - public void onItemClick(Uri uri) {  
431 - playerUtil.start(uri); 497 + public void onItemClick(VoiceMessage voiceMessage, final AnimationDrawable animationDrawable) {
  498 + if (voiceMessage == null) {
  499 + Toast.makeText(this, "数据异常", Toast.LENGTH_LONG).show();
  500 + return;
  501 + }
  502 + if (voiceMessage.getCnVoiceMessage().isSelf()) {
  503 + startVoice(voiceMessage.getCnVoiceMessage().getVoiceUri().getPath(), animationDrawable);
  504 + } else {
  505 + //设置本地已读
  506 + voiceMessage.getCnVoiceMessage().setRead(true);
  507 + String voiceUuid = voiceMessage.getCnVoiceMessage().getUuid();
  508 + final String voicePath = FileUtil.getCacheFilePath(voiceUuid);
  509 + if (FileUtil.isCacheFileExist(voiceUuid)) {
  510 + File file = new File(voicePath);
  511 + if (file.length() < voiceMessage.getCnVoiceMessage().getDataSize()) {
  512 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  513 + return;
  514 + }
  515 + startVoice(voicePath, animationDrawable);
  516 + } else {
  517 + voiceMessage.getCnVoiceMessage().getVoice(voicePath, new IChat.OnDownloadListener() {
  518 + @Override
  519 + public void onSuccess() {
  520 + startVoice(voicePath, animationDrawable);
  521 + }
  522 +
  523 + @Override
  524 + public void onError(int i, String s) {
432 525
  526 + }
  527 + });
  528 + }
  529 + }
  530 + }
  531 +
  532 + @Override
  533 + public void onVideoClick(VideoMessage videoMessage) {
  534 + if (videoMessage.getCnVideoMessage().isSelf()) {
  535 + Intent intent = new Intent(ChatRoomActivity.this, VideoActivity.class);
  536 + intent.putExtra("videoPath", videoMessage.getCnVideoMessage().getVideoPath());
  537 + startActivity(intent);
  538 + } else {
  539 + String videoUuid = videoMessage.getCnVideoMessage().getVideo().getUuid();
  540 + final String videoPath = FileUtil.getCacheFilePath(videoUuid);
  541 + if (FileUtil.isCacheFileExist(videoUuid)) {
  542 + Intent intent = new Intent(ChatRoomActivity.this, VideoActivity.class);
  543 + intent.putExtra("videoPath", videoPath);
  544 + startActivity(intent);
  545 + } else {
  546 + videoMessage.getCnVideoMessage().getVideo().getVideo(videoPath, new IChat.OnDownloadListener() {
  547 + @Override
  548 + public void onSuccess() {
  549 + Intent intent = new Intent(ChatRoomActivity.this, VideoActivity.class);
  550 + intent.putExtra("videoPath", videoPath);
  551 + startActivity(intent);
  552 + }
  553 +
  554 + @Override
  555 + public void onError(int i, String s) {
  556 +
  557 + }
  558 + });
  559 + }
  560 + }
  561 +
  562 + }
  563 +
  564 + @Override
  565 + public void onImageClick(final ImagMessage imagMessage) {
  566 + if (imagMessage.getCnImgMessage().isSelf()) {
  567 + Intent intent = new Intent(ChatRoomActivity.this, ImageViewActivity.class);
  568 + intent.putExtra("path", imagMessage.getCnImgMessage().getImagePath());
  569 + startActivity(intent);
  570 + } else {
  571 + String remoteUuid = imagMessage.getCnImgMessage().getRemoteUuid();
  572 + final String imagePath = FileUtil.getCacheFilePath(remoteUuid);
  573 + if (FileUtil.isCacheFileExist(remoteUuid)) {
  574 + File file = new File(imagePath);
  575 + if (file.length() < imagMessage.getCnImgMessage().getRemoteSize()) {
  576 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  577 + return;
  578 + }
  579 + Intent intent = new Intent(ChatRoomActivity.this, ImageViewActivity.class);
  580 + intent.putExtra("path", imagePath);
  581 + startActivity(intent);
  582 + } else {
  583 + if (imagMessage.isDownloading()) {
  584 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  585 + } else {
  586 + imagMessage.setDownloading(true);
  587 + imagMessage.getCnImgMessage().getRemoteImage(imagePath, new IChat.OnDownloadListener() {
  588 + @Override
  589 + public void onSuccess() {
  590 + imagMessage.setDownloading(false);
  591 + Intent intent = new Intent(ChatRoomActivity.this, ImageViewActivity.class);
  592 + intent.putExtra("path", imagePath);
  593 + startActivity(intent);
  594 + }
  595 +
  596 + @Override
  597 + public void onError(int i, String s) {
  598 + imagMessage.setDownloading(false);
  599 + Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();
  600 + }
  601 + });
  602 + }
  603 + }
  604 + }
433 } 605 }
434 606
435 607
@@ -444,14 +616,15 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -444,14 +616,15 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
444 Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && 616 Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) &&
445 (ContextCompat.checkSelfPermission(context, 617 (ContextCompat.checkSelfPermission(context,
446 Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) 618 Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)
447 - ) { 619 + && (ContextCompat.checkSelfPermission(context,
  620 + Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
448 StartListener(); 621 StartListener();
449 622
450 //判断是否开启语音权限 623 //判断是否开启语音权限
451 } else { 624 } else {
452 //请求获取摄像头权限 625 //请求获取摄像头权限
453 ActivityCompat.requestPermissions((Activity) context, 626 ActivityCompat.requestPermissions((Activity) context,
454 - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, VOICE_REQUEST_CODE); 627 + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, VOICE_REQUEST_CODE);
455 } 628 }
456 } 629 }
457 630
@@ -592,4 +765,16 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL @@ -592,4 +765,16 @@ public class ChatRoomActivity extends AppCompatActivity implements View.OnClickL
592 } 765 }
593 }; 766 };
594 767
  768 + @Override
  769 + protected void onPause() {
  770 + super.onPause();
  771 + MediaUtil.getInstance().stop();
  772 + }
  773 +
  774 + @Override
  775 + protected void onDestroy() {
  776 + super.onDestroy();
  777 + ChatUtil.removeReceiveMessageListener(receiveMessageListener);
  778 + ChatUtil.removeConnectListener(connectListener);
  779 + }
595 } 780 }
app/src/main/java/com/cnlive/im/ui/CommentActivity.java
@@ -13,14 +13,14 @@ import android.widget.Toast; @@ -13,14 +13,14 @@ import android.widget.Toast;
13 13
14 import com.cnlive.im.R; 14 import com.cnlive.im.R;
15 import com.cnlive.im.adapter.CommentAdapter; 15 import com.cnlive.im.adapter.CommentAdapter;
16 -import com.cnlive.libs.util.chat.model.ErrorMessage;  
17 import com.cnlive.libs.util.comment.CommentUtil; 16 import com.cnlive.libs.util.comment.CommentUtil;
18 import com.cnlive.libs.util.comment.base.CommentCallback; 17 import com.cnlive.libs.util.comment.base.CommentCallback;
19 import com.cnlive.libs.util.comment.base.CommentListCallback; 18 import com.cnlive.libs.util.comment.base.CommentListCallback;
20 import com.cnlive.libs.util.comment.base.CommentProgramCallback; 19 import com.cnlive.libs.util.comment.base.CommentProgramCallback;
21 -import com.cnlive.libs.util.model.CommentItem;  
22 -import com.cnlive.libs.util.model.CommentPage;  
23 -import com.cnlive.libs.util.model.CommentProgram; 20 +import com.cnlive.libs.util.comment.model.CommentItem;
  21 +import com.cnlive.libs.util.comment.model.CommentPage;
  22 +import com.cnlive.libs.util.comment.model.CommentProgram;
  23 +import com.cnlive.libs.util.comment.model.ErrorMessage;
24 24
25 import java.util.List; 25 import java.util.List;
26 26
app/src/main/java/com/cnlive/im/ui/ImageViewActivity.java 0 → 100644
  1 +package com.cnlive.im.ui;
  2 +
  3 +import android.app.Activity;
  4 +import android.os.Bundle;
  5 +import android.support.annotation.Nullable;
  6 +import android.widget.ImageView;
  7 +
  8 +import com.bumptech.glide.Glide;
  9 +import com.cnlive.im.R;
  10 +
  11 +/**
  12 + * Created by gujun on 2017/12/18.
  13 + */
  14 +
  15 +public class ImageViewActivity extends Activity {
  16 +
  17 + private ImageView imageView;
  18 +
  19 + private String imagePath;
  20 +
  21 + @Override
  22 + protected void onCreate(@Nullable Bundle savedInstanceState) {
  23 + super.onCreate(savedInstanceState);
  24 + setContentView(R.layout.activity_image_view);
  25 + imageView = (ImageView) findViewById(R.id.image);
  26 + imagePath = getIntent().getStringExtra("path");
  27 + Glide.with(this).load(imagePath).into(imageView);
  28 + }
  29 +}
app/src/main/java/com/cnlive/im/ui/PrivateActivity.java
@@ -6,6 +6,9 @@ import android.content.Context; @@ -6,6 +6,9 @@ import android.content.Context;
6 import android.content.Intent; 6 import android.content.Intent;
7 import android.content.pm.PackageManager; 7 import android.content.pm.PackageManager;
8 import android.database.Cursor; 8 import android.database.Cursor;
  9 +import android.graphics.Bitmap;
  10 +import android.graphics.drawable.AnimationDrawable;
  11 +import android.media.ThumbnailUtils;
9 import android.net.Uri; 12 import android.net.Uri;
10 import android.os.Build; 13 import android.os.Build;
11 import android.os.Bundle; 14 import android.os.Bundle;
@@ -29,33 +32,38 @@ import android.widget.Button; @@ -29,33 +32,38 @@ import android.widget.Button;
29 import android.widget.EditText; 32 import android.widget.EditText;
30 import android.widget.ImageView; 33 import android.widget.ImageView;
31 import android.widget.LinearLayout; 34 import android.widget.LinearLayout;
32 -import android.widget.ListView;  
33 import android.widget.RelativeLayout; 35 import android.widget.RelativeLayout;
34 import android.widget.TextView; 36 import android.widget.TextView;
35 import android.widget.Toast; 37 import android.widget.Toast;
36 38
37 import com.cnlive.im.R; 39 import com.cnlive.im.R;
38 import com.cnlive.im.adapter.ChatRoomAdpter; 40 import com.cnlive.im.adapter.ChatRoomAdpter;
39 -import com.cnlive.im.adapter.base.VoiceItemClickListener; 41 +import com.cnlive.im.adapter.base.ItemClickListener;
40 import com.cnlive.im.mode.CNMessageModole; 42 import com.cnlive.im.mode.CNMessageModole;
41 import com.cnlive.im.mode.ImagMessage; 43 import com.cnlive.im.mode.ImagMessage;
42 import com.cnlive.im.mode.StringMessage; 44 import com.cnlive.im.mode.StringMessage;
  45 +import com.cnlive.im.mode.VideoMessage;
43 import com.cnlive.im.mode.VoiceMessage; 46 import com.cnlive.im.mode.VoiceMessage;
44 import com.cnlive.im.util.AudioRecordUtil; 47 import com.cnlive.im.util.AudioRecordUtil;
  48 +import com.cnlive.im.util.FileUtil;
  49 +import com.cnlive.im.util.MediaUtil;
45 import com.cnlive.im.util.MessageType; 50 import com.cnlive.im.util.MessageType;
46 -import com.cnlive.im.util.PlayerUtil;  
47 import com.cnlive.im.util.TimeUtils; 51 import com.cnlive.im.util.TimeUtils;
48 import com.cnlive.im.util.ToStringUtils; 52 import com.cnlive.im.util.ToStringUtils;
49 import com.cnlive.libs.util.chat.ChatUtil; 53 import com.cnlive.libs.util.chat.ChatUtil;
50 import com.cnlive.libs.util.chat.base.IChat; 54 import com.cnlive.libs.util.chat.base.IChat;
  55 +import com.cnlive.libs.util.chat.model.CNBaseMessage;
51 import com.cnlive.libs.util.chat.model.CNImgMessage; 56 import com.cnlive.libs.util.chat.model.CNImgMessage;
52 import com.cnlive.libs.util.chat.model.CNMessage; 57 import com.cnlive.libs.util.chat.model.CNMessage;
53 import com.cnlive.libs.util.chat.model.CNUserInfo; 58 import com.cnlive.libs.util.chat.model.CNUserInfo;
  59 +import com.cnlive.libs.util.chat.model.CNVideoMessage;
54 import com.cnlive.libs.util.chat.model.CNVoiceMessage; 60 import com.cnlive.libs.util.chat.model.CNVoiceMessage;
55 61
56 import org.json.JSONException; 62 import org.json.JSONException;
57 import org.json.JSONObject; 63 import org.json.JSONObject;
58 64
  65 +import java.io.File;
  66 +import java.io.FileInputStream;
59 import java.util.ArrayList; 67 import java.util.ArrayList;
60 68
61 import static com.cnlive.im.R.id.opposite_id_edit; 69 import static com.cnlive.im.R.id.opposite_id_edit;
@@ -64,10 +72,12 @@ import static com.cnlive.im.R.id.opposite_id_edit; @@ -64,10 +72,12 @@ import static com.cnlive.im.R.id.opposite_id_edit;
64 * Created by Lynn on 2017/7/24. 72 * Created by Lynn on 2017/7/24.
65 */ 73 */
66 74
67 -public class PrivateActivity extends AppCompatActivity implements View.OnClickListener, VoiceItemClickListener { 75 +public class PrivateActivity extends AppCompatActivity implements View.OnClickListener, ItemClickListener {
68 76
69 private static final String TAG = "PrivateChatActivity"; 77 private static final String TAG = "PrivateChatActivity";
70 78
  79 + private final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 0x2001;
  80 +
71 // 所需的全部权限 81 // 所需的全部权限
72 static final String[] PERMISSIONS = new String[]{ 82 static final String[] PERMISSIONS = new String[]{
73 Manifest.permission.RECORD_AUDIO, 83 Manifest.permission.RECORD_AUDIO,
@@ -87,7 +97,7 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -87,7 +97,7 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
87 private EditText messageContent; 97 private EditText messageContent;
88 private Button sendMessageBtn; 98 private Button sendMessageBtn;
89 private ChatRoomAdpter chatListAdapter; 99 private ChatRoomAdpter chatListAdapter;
90 - private ArrayList<Object> messageList = new ArrayList<>(); 100 + private ArrayList<String> messageList = new ArrayList<>();
91 // private CNMessage cnMessage; 101 // private CNMessage cnMessage;
92 private LinearLayout linearLayoutUseID; 102 private LinearLayout linearLayoutUseID;
93 private EditText user_id_edit; 103 private EditText user_id_edit;
@@ -108,7 +118,6 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -108,7 +118,6 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
108 private ImageView keybordBtn; 118 private ImageView keybordBtn;
109 private Button sendVoice; 119 private Button sendVoice;
110 private AudioRecordUtil mAudioRecordUtil; 120 private AudioRecordUtil mAudioRecordUtil;
111 - private PlayerUtil playerUtil;  
112 private String mFilePath; 121 private String mFilePath;
113 private PopupWindowFactory mPop; 122 private PopupWindowFactory mPop;
114 private RelativeLayout privateLayout; 123 private RelativeLayout privateLayout;
@@ -132,9 +141,8 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -132,9 +141,8 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
132 mAudioRecordUtil.setOnAudioStatusUpdateListener(onAudioStatusUpdateListener); 141 mAudioRecordUtil.setOnAudioStatusUpdateListener(onAudioStatusUpdateListener);
133 mHandler = new Handler(); 142 mHandler = new Handler();
134 ChatUtil.setOnConnectStatusListener(connectStatusListener); 143 ChatUtil.setOnConnectStatusListener(connectStatusListener);
135 - ChatUtil.setOnReceiveMessageListener(receiveMessageListener); 144 + ChatUtil.setOnReceivePrivateMessageListener(receiveMessageListener);
136 requestPermission(); 145 requestPermission();
137 - playerUtil = new PlayerUtil(this);  
138 } 146 }
139 147
140 private void initView() { 148 private void initView() {
@@ -184,6 +192,9 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -184,6 +192,9 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
184 chatListView.setLayoutManager(new LinearLayoutManager(PrivateActivity.this)); 192 chatListView.setLayoutManager(new LinearLayoutManager(PrivateActivity.this));
185 chatListView.setAdapter(chatListAdapter); 193 chatListView.setAdapter(chatListAdapter);
186 194
  195 + findViewById(R.id.videoBtn).setOnClickListener(this);
  196 + findViewById(R.id.ugcVideoBtn).setOnClickListener(this);
  197 +
187 StartListener(); 198 StartListener();
188 } 199 }
189 200
@@ -251,9 +262,31 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -251,9 +262,31 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
251 case R.id.ima_send: 262 case R.id.ima_send:
252 sendMessage(IMAGE_MESSAGE); 263 sendMessage(IMAGE_MESSAGE);
253 break; 264 break;
  265 + case R.id.videoBtn:
  266 + openSystemRecorder();
  267 + break;
  268 + case R.id.ugcVideoBtn:
  269 +
  270 + break;
254 } 271 }
255 } 272 }
256 273
  274 + private void openSystemRecorder() {
  275 + // 创建拍照Intent并将控制权返回给调用的程序
  276 + Intent intent = new Intent();
  277 + intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
  278 + intent.addCategory(Intent.CATEGORY_DEFAULT);
  279 +
  280 + // 保存录像到指定的路径
  281 + File file = new File("/sdcard/video.mp4");
  282 + Uri uri = Uri.fromFile(file);
  283 + intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
  284 +
  285 + // 启动图像捕获Intent
  286 + startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
  287 + }
  288 +
  289 +
257 private void sendMessage(String type) { 290 private void sendMessage(String type) {
258 if (sendInfo == 2) { 291 if (sendInfo == 2) {
259 Toast.makeText(this, "等待对方接受邀请", Toast.LENGTH_SHORT).show(); 292 Toast.makeText(this, "等待对方接受邀请", Toast.LENGTH_SHORT).show();
@@ -329,6 +362,12 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -329,6 +362,12 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
329 Uri uri = Uri.parse("file://" + picturePath); 362 Uri uri = Uri.parse("file://" + picturePath);
330 ChatUtil.sendImaMessage(IChat.PRIVATE, oppositeID, uri, uri, sendMessageListener); 363 ChatUtil.sendImaMessage(IChat.PRIVATE, oppositeID, uri, uri, sendMessageListener);
331 break; 364 break;
  365 + case CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE:
  366 + String videoPath = data.getData().getPath();
  367 + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Images.Thumbnails.FULL_SCREEN_KIND);
  368 + String imgPath = FileUtil.createFile(bitmap, System.currentTimeMillis() + "");
  369 + ChatUtil.sendVideoMessage(IChat.PRIVATE, oppositeID, videoPath, imgPath, MediaUtil.getInstance().getDuration(videoPath), sendMessageListener);
  370 + break;
332 371
333 default: 372 default:
334 break; 373 break;
@@ -365,120 +404,110 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -365,120 +404,110 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
365 /** 404 /**
366 * 发送消息监听 405 * 发送消息监听
367 */ 406 */
368 -  
369 private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() { 407 private IChat.OnSendMessageListener sendMessageListener = new IChat.OnSendMessageListener() {
370 @Override 408 @Override
371 - public void onAttached(Object o) { 409 + public void onAttached(CNBaseMessage o) {
  410 + showMessage(o, false);
372 } 411 }
373 412
374 @Override 413 @Override
375 - public void onSuccess(final Object o) throws JSONException {  
376 - if (View.VISIBLE == vistor_btn.getVisibility()) {  
377 - vistor_btn.setVisibility(View.GONE);  
378 - }  
379 -  
380 - mHandler.post(new Runnable() {  
381 - @Override  
382 - public void run() {  
383 - if (o instanceof CNMessage) {  
384 - CNMessage o1 = (CNMessage) o;  
385 - JSONObject jsonObject = null;  
386 - try {  
387 - jsonObject = new JSONObject(o1.getContent().toString());  
388 - String type = (String) jsonObject.get("type");  
389 - String message = (String) jsonObject.get("message");  
390 - Toast.makeText(PrivateActivity.this, "发送消息成功", Toast.LENGTH_SHORT).show();  
391 - if ("3".equals(type) && message.equals("你好我们可以进行私聊吗")) {  
392 - sendInfo = 2;  
393 - Toast.makeText(PrivateActivity.this, "申请已发送等待对方验证", Toast.LENGTH_SHORT).show();  
394 - } else if ("3".equals(type) && message.equals("拒绝")) {  
395 - sendInfo = 5;  
396 - } else if ("3".equals(type) && message.equals("同意")) {  
397 - sendInfo = 1;  
398 - } else if ("4".equals(type)) {  
399 - chatListAdapter.addItem(new StringMessage(MessageType.stringMessage, o1, true));  
400 - chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);  
401 -  
402 - }  
403 - } catch (JSONException e) {  
404 -  
405 -  
406 - }  
407 - } else if (o instanceof CNImgMessage) {  
408 - CNImgMessage o1 = (CNImgMessage) o;  
409 - chatListAdapter.addItem(new ImagMessage(MessageType.imaMessage, o1, true));  
410 - chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);  
411 - } else if (o instanceof CNVoiceMessage) {  
412 - CNVoiceMessage o1 = (CNVoiceMessage) o;  
413 - VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, true);  
414 - chatListAdapter.addItem(voiceMessage);  
415 - //发送成功后删除保存在本地的录制文件  
416 - mAudioRecordUtil.deleteRecordFile(mFilePath);  
417 - chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);  
418 - }  
419 - }  
420 - }); 414 + public void onSuccess(final CNBaseMessage o) {
  415 + updateItem(o);
421 } 416 }
422 417
423 @Override 418 @Override
424 - public void onError(Object o, int i, String s) { 419 + public void onError(CNBaseMessage o, int i, String s) {
  420 + updateItem(o);
425 } 421 }
426 }; 422 };
427 423
428 -  
429 //连接状态监听 424 //连接状态监听
430 private IChat.OnConnectStatusListener connectStatusListener = new IChat.OnConnectStatusListener() { 425 private IChat.OnConnectStatusListener connectStatusListener = new IChat.OnConnectStatusListener() {
431 @Override 426 @Override
432 public void onConnectStatus(int i, String s) { 427 public void onConnectStatus(int i, String s) {
433 - Log.i(TAG, "私聊连接状态监听私聊" + i + " " + s);  
434 -  
435 - 428 + Log.i(TAG, "连接状态监听" + i + " " + s);
436 } 429 }
437 }; 430 };
  431 +
  432 +
438 //接收消息监听 433 //接收消息监听
439 private IChat.OnReceiveMessageListener receiveMessageListener = new IChat.OnReceiveMessageListener() { 434 private IChat.OnReceiveMessageListener receiveMessageListener = new IChat.OnReceiveMessageListener() {
440 @Override 435 @Override
441 - public void processMessage(final Object o) {  
442 - mHandler.post(new Runnable() {  
443 - @Override  
444 - public void run() {  
445 - if (o instanceof CNMessage) {  
446 - CNMessage o1 = (CNMessage) o;  
447 - JSONObject jsonObject = null;  
448 - try {  
449 - jsonObject = new JSONObject(o1.getContent().toString());  
450 - String type = (String) jsonObject.get("type");  
451 - if ("3".equals(type) && "你好我们可以进行私聊吗".equals(jsonObject.get("message"))) {  
452 - vistor_btn.setVisibility(View.GONE);  
453 - agree_reject_lin.setVisibility(View.VISIBLE);  
454 - } else if ("3".equals(type) && "同意".equals(jsonObject.get("message"))) {  
455 - sendInfo = 1;  
456 - } else if ("3".equals(type) && "拒绝".equals(jsonObject.get("message"))) {  
457 - sendInfo = 4;  
458 - } else if ("4".equals(type)) {  
459 - Log.v(TAG, o1.getContent().toString());  
460 - chatListAdapter.addItem(new StringMessage(MessageType.stringMessage, o1, false));  
461 - chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);  
462 - } 436 + public void processMessage(final CNBaseMessage o) {
  437 + showMessage(o, true);
  438 + }
  439 + };
463 440
464 - } catch (JSONException e) {  
465 - e.printStackTrace();  
466 - }  
467 - } else if (o instanceof CNImgMessage) {  
468 - CNImgMessage o1 = (CNImgMessage) o;  
469 - chatListAdapter.addItem(new ImagMessage(MessageType.imaMessage, o1, false));  
470 - chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);  
471 - } else if (o instanceof CNVoiceMessage) {  
472 - CNVoiceMessage o1 = (CNVoiceMessage) o;  
473 - VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, false);  
474 - chatListAdapter.addItem(voiceMessage); 441 + /**
  442 + * 更新消息
  443 + */
  444 + public void updateItem(CNBaseMessage o) {
  445 + int updateIndex = messageList.indexOf(o.getMessageId());
  446 + if (updateIndex < 0 || chatListAdapter.getItemCount() <= 0) return;
  447 + if (o.getMsgType() == IChat.CN_MSG_TYPE_TEXT) {
  448 + CNMessage o1 = (CNMessage) o;
  449 + chatListAdapter.updateItem(new StringMessage(MessageType.stringMessage, o1, o1.isSelf()), updateIndex);
  450 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_IMAGE) {
  451 + CNImgMessage o1 = (CNImgMessage) o;
  452 + chatListAdapter.updateItem(new ImagMessage(MessageType.imaMessage, o1, o1.isSelf()), updateIndex);
  453 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VOICE) {
  454 + CNVoiceMessage o1 = (CNVoiceMessage) o;
  455 + VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, o1.isSelf());
  456 + chatListAdapter.updateItem(voiceMessage, updateIndex);
  457 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VIDEO) {
  458 + CNVideoMessage ol = (CNVideoMessage) o;
  459 + VideoMessage videoMessage = new VideoMessage(MessageType.videoMessage, ol, ol.isSelf());
  460 + chatListAdapter.updateItem(videoMessage, updateIndex);
  461 + }
  462 + }
  463 +
  464 + /**
  465 + * 展示消息
  466 + *
  467 + * @param o
  468 + */
  469 + private void showMessage(CNBaseMessage o, boolean isReceivedMsg) {
  470 + messageList.add(o.getMessageId());
  471 + if (o.getMsgType() == IChat.CN_MSG_TYPE_TEXT) {
  472 + if (isReceivedMsg) {
  473 + CNMessage o1 = (CNMessage) o;
  474 + JSONObject jsonObject = null;
  475 + try {
  476 + jsonObject = new JSONObject(o1.getContent().toString());
  477 + String type = (String) jsonObject.get("type");
  478 + if ("3".equals(type) && "你好我们可以进行私聊吗".equals(jsonObject.get("message"))) {
  479 + vistor_btn.setVisibility(View.GONE);
  480 + agree_reject_lin.setVisibility(View.VISIBLE);
  481 + } else if ("3".equals(type) && "同意".equals(jsonObject.get("message"))) {
  482 + sendInfo = 1;
  483 + } else if ("3".equals(type) && "拒绝".equals(jsonObject.get("message"))) {
  484 + sendInfo = 4;
  485 + } else if ("4".equals(type)) {
  486 + Log.v(TAG, o1.getContent().toString());
  487 + chatListAdapter.addItem(new StringMessage(MessageType.stringMessage, o1, false));
475 chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1); 488 chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);
476 } 489 }
  490 + } catch (JSONException e) {
  491 + e.printStackTrace();
477 } 492 }
478 - });  
479 - 493 + } else {
  494 + CNMessage o1 = (CNMessage) o;
  495 + chatListAdapter.addItem(new StringMessage(MessageType.stringMessage, o1, o1.isSelf()));
  496 + }
  497 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_IMAGE) {
  498 + CNImgMessage o1 = (CNImgMessage) o;
  499 + chatListAdapter.addItem(new ImagMessage(MessageType.imaMessage, o1, o1.isSelf()));
  500 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VOICE) {
  501 + CNVoiceMessage o1 = (CNVoiceMessage) o;
  502 + VoiceMessage voiceMessage = new VoiceMessage(MessageType.voiceMessage, o1, o1.isSelf());
  503 + chatListAdapter.addItem(voiceMessage);
  504 + } else if (o.getMsgType() == IChat.CN_MSG_TYPE_VIDEO) {
  505 + CNVideoMessage ol = (CNVideoMessage) o;
  506 + VideoMessage videoMessage = new VideoMessage(MessageType.videoMessage, ol, ol.isSelf());
  507 + chatListAdapter.addItem(videoMessage);
480 } 508 }
481 - }; 509 + chatListView.smoothScrollToPosition(chatListAdapter.getItemCount() - 1);
  510 + }
482 511
483 /** 512 /**
484 * 开启扫描之前判断权限是否打开 513 * 开启扫描之前判断权限是否打开
@@ -489,14 +518,15 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -489,14 +518,15 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
489 Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && 518 Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) &&
490 (ContextCompat.checkSelfPermission(context, 519 (ContextCompat.checkSelfPermission(context,
491 Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) 520 Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)
492 - ) { 521 + && (ContextCompat.checkSelfPermission(context,
  522 + Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
493 StartListener(); 523 StartListener();
494 524
495 //判断是否开启语音权限 525 //判断是否开启语音权限
496 } else { 526 } else {
497 //请求获取摄像头权限 527 //请求获取摄像头权限
498 ActivityCompat.requestPermissions((Activity) context, 528 ActivityCompat.requestPermissions((Activity) context,
499 - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, VOICE_REQUEST_CODE); 529 + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, VOICE_REQUEST_CODE);
500 } 530 }
501 } 531 }
502 532
@@ -638,8 +668,149 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi @@ -638,8 +668,149 @@ public class PrivateActivity extends AppCompatActivity implements View.OnClickLi
638 } 668 }
639 }; 669 };
640 670
  671 + /**
  672 + * 播放语音文件
  673 + *
  674 + * @param voicePath
  675 + * @param animationDrawable
  676 + */
  677 + private void startVoice(String voicePath, final AnimationDrawable animationDrawable) {
  678 + try {
  679 + FileInputStream fis = new FileInputStream(voicePath);
  680 + MediaUtil.getInstance().play(fis);
  681 + animationDrawable.start();
  682 + MediaUtil.getInstance().setEventListener(new MediaUtil.EventListener() {
  683 + @Override
  684 + public void onStop() {
  685 + animationDrawable.stop();
  686 + animationDrawable.selectDrawable(0);
  687 + }
  688 + });
  689 + } catch (Exception e) {
  690 + }
  691 + }
  692 +
  693 + @Override
  694 + public void onItemClick(VoiceMessage voiceMessage, final AnimationDrawable animationDrawable) {
  695 + if (voiceMessage == null) {
  696 + Toast.makeText(this, "数据异常", Toast.LENGTH_LONG).show();
  697 + return;
  698 + }
  699 + if (voiceMessage.getCnVoiceMessage().isSelf()) {
  700 + startVoice(voiceMessage.getCnVoiceMessage().getVoiceUri().getPath(), animationDrawable);
  701 + } else {
  702 + //设置本地已读
  703 + voiceMessage.getCnVoiceMessage().setRead(true);
  704 + String voiceUuid = voiceMessage.getCnVoiceMessage().getUuid();
  705 + final String voicePath = FileUtil.getCacheFilePath(voiceUuid);
  706 + if (FileUtil.isCacheFileExist(voiceUuid)) {
  707 + File file = new File(voicePath);
  708 + if (file.length() < voiceMessage.getCnVoiceMessage().getDataSize()) {
  709 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  710 + return;
  711 + }
  712 + startVoice(voicePath, animationDrawable);
  713 + } else {
  714 + voiceMessage.getCnVoiceMessage().getVoice(voicePath, new IChat.OnDownloadListener() {
  715 + @Override
  716 + public void onSuccess() {
  717 + startVoice(voicePath, animationDrawable);
  718 + }
  719 +
  720 + @Override
  721 + public void onError(int i, String s) {
  722 +
  723 + }
  724 + });
  725 + }
  726 + }
  727 + }
  728 +
  729 + @Override
  730 + public void onVideoClick(VideoMessage videoMessage) {
  731 + if (videoMessage.getCnVideoMessage().isSelf()) {
  732 + Intent intent = new Intent(PrivateActivity.this, VideoActivity.class);
  733 + intent.putExtra("videoPath", videoMessage.getCnVideoMessage().getVideoPath());
  734 + startActivity(intent);
  735 + } else {
  736 + String videoUuid = videoMessage.getCnVideoMessage().getVideo().getUuid();
  737 + final String videoPath = FileUtil.getCacheFilePath(videoUuid);
  738 + if (FileUtil.isCacheFileExist(videoUuid)) {
  739 + Intent intent = new Intent(PrivateActivity.this, VideoActivity.class);
  740 + intent.putExtra("videoPath", videoPath);
  741 + startActivity(intent);
  742 + } else {
  743 + videoMessage.getCnVideoMessage().getVideo().getVideo(videoPath, new IChat.OnDownloadListener() {
  744 + @Override
  745 + public void onSuccess() {
  746 + Intent intent = new Intent(PrivateActivity.this, VideoActivity.class);
  747 + intent.putExtra("videoPath", videoPath);
  748 + startActivity(intent);
  749 + }
  750 +
  751 + @Override
  752 + public void onError(int i, String s) {
  753 +
  754 + }
  755 + });
  756 + }
  757 + }
  758 +
  759 + }
  760 +
  761 + @Override
  762 + public void onImageClick(final ImagMessage imagMessage) {
  763 + if (imagMessage.getCnImgMessage().isSelf()) {
  764 + Intent intent = new Intent(PrivateActivity.this, ImageViewActivity.class);
  765 + intent.putExtra("path", imagMessage.getCnImgMessage().getImagePath());
  766 + startActivity(intent);
  767 + } else {
  768 + String remoteUuid = imagMessage.getCnImgMessage().getRemoteUuid();
  769 + final String imagePath = FileUtil.getCacheFilePath(remoteUuid);
  770 + if (FileUtil.isCacheFileExist(remoteUuid)) {
  771 + File file = new File(imagePath);
  772 + if (file.length() < imagMessage.getCnImgMessage().getRemoteSize()) {
  773 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  774 + return;
  775 + }
  776 + Intent intent = new Intent(PrivateActivity.this, ImageViewActivity.class);
  777 + intent.putExtra("path", imagePath);
  778 + startActivity(intent);
  779 + } else {
  780 + if (imagMessage.isDownloading()) {
  781 + Toast.makeText(context, "请稍等,正在下载...", Toast.LENGTH_SHORT).show();
  782 + } else {
  783 + imagMessage.setDownloading(true);
  784 + imagMessage.getCnImgMessage().getRemoteImage(imagePath, new IChat.OnDownloadListener() {
  785 + @Override
  786 + public void onSuccess() {
  787 + imagMessage.setDownloading(false);
  788 + Intent intent = new Intent(PrivateActivity.this, ImageViewActivity.class);
  789 + intent.putExtra("path", imagePath);
  790 + startActivity(intent);
  791 + }
  792 +
  793 + @Override
  794 + public void onError(int i, String s) {
  795 + imagMessage.setDownloading(false);
  796 + Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();
  797 + }
  798 + });
  799 + }
  800 + }
  801 + }
  802 + }
  803 +
  804 + @Override
  805 + protected void onPause() {
  806 + super.onPause();
  807 + MediaUtil.getInstance().stop();
  808 + }
  809 +
641 @Override 810 @Override
642 - public void onItemClick(Uri uri) {  
643 - playerUtil.start(uri); 811 + protected void onDestroy() {
  812 + super.onDestroy();
  813 + ChatUtil.removeReceiveMessageListener(receiveMessageListener);
  814 + ChatUtil.removeConnectListener(connectListener);
644 } 815 }
645 } 816 }
app/src/main/java/com/cnlive/im/ui/VideoActivity.java 0 → 100644
  1 +package com.cnlive.im.ui;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Intent;
  5 +import android.media.MediaPlayer;
  6 +import android.os.Bundle;
  7 +import android.support.annotation.Nullable;
  8 +import android.widget.VideoView;
  9 +
  10 +import com.cnlive.im.R;
  11 +
  12 +/**
  13 + * Created by gujun on 2017/12/12.
  14 + */
  15 +
  16 +public class VideoActivity extends Activity {
  17 + private String videoPath;
  18 + private VideoView videoView;
  19 + private boolean isStart = false;
  20 +
  21 + @Override
  22 + protected void onCreate(@Nullable Bundle savedInstanceState) {
  23 + super.onCreate(savedInstanceState);
  24 + setContentView(R.layout.activity_play);
  25 + init(getIntent());
  26 + }
  27 +
  28 + @Override
  29 + protected void onNewIntent(Intent intent) {
  30 + super.onNewIntent(intent);
  31 + init(intent);
  32 + }
  33 +
  34 + private void init(Intent intent) {
  35 + videoPath = intent.getStringExtra("videoPath");
  36 +
  37 + videoView = (VideoView) findViewById(R.id.video);
  38 + videoView.setVideoPath(videoPath);
  39 + videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
  40 + @Override
  41 + public void onPrepared(MediaPlayer mp) {
  42 + isStart = true;
  43 + videoView.start();
  44 + }
  45 + });
  46 + }
  47 +
  48 + @Override
  49 + protected void onResume() {
  50 + super.onResume();
  51 + if (videoView != null && isStart) {
  52 + videoView.start();
  53 + }
  54 + }
  55 +
  56 + @Override
  57 + protected void onPause() {
  58 + super.onPause();
  59 + if (videoView != null && isStart) {
  60 + videoView.pause();
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + protected void onDestroy() {
  66 + super.onDestroy();
  67 + if (videoView != null) {
  68 + videoView.stopPlayback();
  69 + videoView = null;
  70 + }
  71 + }
  72 +}
app/src/main/java/com/cnlive/im/util/FileUtil.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.ContentUris;
  5 +import android.content.Context;
  6 +import android.database.Cursor;
  7 +import android.graphics.Bitmap;
  8 +import android.net.Uri;
  9 +import android.os.Build;
  10 +import android.os.Environment;
  11 +import android.provider.DocumentsContract;
  12 +import android.provider.MediaStore;
  13 +import android.util.Log;
  14 +
  15 +import com.cnlive.im.CNLiveApplication;
  16 +
  17 +import java.io.ByteArrayOutputStream;
  18 +import java.io.File;
  19 +import java.io.FileOutputStream;
  20 +import java.io.IOException;
  21 +
  22 +/**
  23 + * 文件工具类
  24 + */
  25 +public class FileUtil {
  26 +
  27 + private static final String TAG = "FileUtil";
  28 + private static String pathDiv = "/";
  29 + private static File cacheDir = !isExternalStorageWritable() ? CNLiveApplication.getContext().getFilesDir() : CNLiveApplication.getContext().getExternalCacheDir();
  30 +
  31 + private FileUtil() {
  32 + /* cannot be instantiated */
  33 + throw new UnsupportedOperationException("cannot be instantiated");
  34 + }
  35 +
  36 +
  37 + /**
  38 + * 创建临时文件
  39 + *
  40 + * @param type 文件类型
  41 + */
  42 + public static File getTempFile(FileType type) {
  43 + try {
  44 + File file = File.createTempFile(type.toString(), null, cacheDir);
  45 + file.deleteOnExit();
  46 + return file;
  47 + } catch (IOException e) {
  48 + return null;
  49 + }
  50 + }
  51 +
  52 +
  53 + /**
  54 + * 获取缓存文件地址
  55 + */
  56 + public static String getCacheFilePath(String fileName) {
  57 + return cacheDir.getAbsolutePath() + pathDiv + fileName;
  58 + }
  59 +
  60 +
  61 + /**
  62 + * 判断缓存文件是否存在
  63 + */
  64 + public static boolean isCacheFileExist(String fileName) {
  65 + File file = new File(getCacheFilePath(fileName));
  66 + return file.exists();
  67 + }
  68 +
  69 +
  70 + /**
  71 + * 将图片存储为文件
  72 + *
  73 + * @param bitmap 图片
  74 + */
  75 + public static String createFile(Bitmap bitmap, String filename) {
  76 + File f = new File(cacheDir, filename);
  77 + try {
  78 + if (f.createNewFile()) {
  79 + ByteArrayOutputStream bos = new ByteArrayOutputStream();
  80 + bitmap.compress(Bitmap.CompressFormat.PNG, 0, bos);
  81 + byte[] bitmapdata = bos.toByteArray();
  82 + FileOutputStream fos = new FileOutputStream(f);
  83 + fos.write(bitmapdata);
  84 + fos.flush();
  85 + fos.close();
  86 + }
  87 + } catch (IOException e) {
  88 + Log.e(TAG, "create bitmap file error" + e);
  89 + }
  90 + if (f.exists()) {
  91 + return f.getAbsolutePath();
  92 + }
  93 + return null;
  94 + }
  95 +
  96 + /**
  97 + * 将数据存储为文件
  98 + *
  99 + * @param data 数据
  100 + */
  101 + public static void createFile(byte[] data, String filename) {
  102 + File f = new File(cacheDir, filename);
  103 + try {
  104 + if (f.createNewFile()) {
  105 + FileOutputStream fos = new FileOutputStream(f);
  106 + fos.write(data);
  107 + fos.flush();
  108 + fos.close();
  109 + }
  110 + } catch (IOException e) {
  111 + Log.e(TAG, "create file error" + e);
  112 + }
  113 + }
  114 +
  115 +
  116 + /**
  117 + * 判断缓存文件是否存在
  118 + */
  119 + public static boolean isFileExist(String fileName, String type) {
  120 + if (isExternalStorageWritable()) {
  121 + File dir = CNLiveApplication.getContext().getExternalFilesDir(type);
  122 + if (dir != null) {
  123 + File f = new File(dir, fileName);
  124 + return f.exists();
  125 + }
  126 + }
  127 + return false;
  128 + }
  129 +
  130 +
  131 + /**
  132 + * 将数据存储为文件
  133 + *
  134 + * @param data 数据
  135 + * @param fileName 文件名
  136 + * @param type 文件类型
  137 + */
  138 + public static File createFile(byte[] data, String fileName, String type) {
  139 + if (isExternalStorageWritable()) {
  140 + File dir = CNLiveApplication.getContext().getExternalFilesDir(type);
  141 + if (dir != null) {
  142 + File f = new File(dir, fileName);
  143 + try {
  144 + if (f.createNewFile()) {
  145 + FileOutputStream fos = new FileOutputStream(f);
  146 + fos.write(data);
  147 + fos.flush();
  148 + fos.close();
  149 + return f;
  150 + }
  151 + } catch (IOException e) {
  152 + Log.e(TAG, "create file error" + e);
  153 + return null;
  154 + }
  155 + }
  156 + }
  157 + return null;
  158 + }
  159 +
  160 +
  161 + /**
  162 + * 从URI获取图片文件地址
  163 + *
  164 + * @param context 上下文
  165 + * @param uri 文件uri
  166 + */
  167 + public static String getImageFilePath(Context context, Uri uri) {
  168 + if (uri == null) {
  169 + return null;
  170 + }
  171 + String path = null;
  172 + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  173 + if (isKitKat) {
  174 + if (!isMediaDocument(uri)) {
  175 + try {
  176 + final String docId = DocumentsContract.getDocumentId(uri);
  177 + final String[] split = docId.split(":");
  178 + Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  179 + final String selection = "_id=?";
  180 + final String[] selectionArgs = new String[]{
  181 + split[1]
  182 + };
  183 + path = getDataColumn(context, contentUri, selection, selectionArgs);
  184 + } catch (IllegalArgumentException e) {
  185 + path = null;
  186 + }
  187 + }
  188 + }
  189 + if (path == null) {
  190 + String[] projection = {MediaStore.Images.Media.DATA};
  191 + Cursor cursor = ((Activity) context).managedQuery(uri, projection, null, null, null);
  192 + if (cursor != null) {
  193 + int column_index = cursor
  194 + .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
  195 + cursor.moveToFirst();
  196 + return cursor.getString(column_index);
  197 + }
  198 +
  199 + path = null;
  200 + }
  201 + return path;
  202 + }
  203 +
  204 +
  205 + /**
  206 + * 从URI获取文件地址
  207 + *
  208 + * @param context 上下文
  209 + * @param uri 文件uri
  210 + */
  211 + public static String getFilePath(Context context, Uri uri) {
  212 + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  213 + // DocumentProvider
  214 + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
  215 + // ExternalStorageProvider
  216 + if (isExternalStorageDocument(uri)) {
  217 + final String docId = DocumentsContract.getDocumentId(uri);
  218 + final String[] split = docId.split(":");
  219 + final String type = split[0];
  220 +
  221 + if ("primary".equalsIgnoreCase(type)) {
  222 + return Environment.getExternalStorageDirectory() + "/" + split[1];
  223 + }
  224 +
  225 + // TODO handle non-primary volumes
  226 + }
  227 + // DownloadsProvider
  228 + else if (isDownloadsDocument(uri)) {
  229 +
  230 + final String id = DocumentsContract.getDocumentId(uri);
  231 + final Uri contentUri = ContentUris.withAppendedId(
  232 + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
  233 +
  234 + return getDataColumn(context, contentUri, null, null);
  235 + }
  236 + // MediaProvider
  237 + else if (isMediaDocument(uri)) {
  238 + final String docId = DocumentsContract.getDocumentId(uri);
  239 + final String[] split = docId.split(":");
  240 + final String type = split[0];
  241 +
  242 + Uri contentUri = null;
  243 + if ("image".equals(type)) {
  244 + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  245 + } else if ("video".equals(type)) {
  246 + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  247 + } else if ("audio".equals(type)) {
  248 + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  249 + }
  250 +
  251 + final String selection = "_id=?";
  252 + final String[] selectionArgs = new String[]{
  253 + split[1]
  254 + };
  255 +
  256 + return getDataColumn(context, contentUri, selection, selectionArgs);
  257 + }
  258 + }
  259 + // MediaStore (and general)
  260 + else if ("content".equalsIgnoreCase(uri.getScheme())) {
  261 + return getDataColumn(context, uri, null, null);
  262 + }
  263 + // File
  264 + else if ("file".equalsIgnoreCase(uri.getScheme())) {
  265 + return uri.getPath();
  266 + }
  267 +
  268 + return null;
  269 + }
  270 +
  271 +
  272 + /**
  273 + * Get the value of the data column for this Uri. This is useful for
  274 + * MediaStore Uris, and other file-based ContentProviders.
  275 + *
  276 + * @param context The context.
  277 + * @param uri The Uri to query.
  278 + * @param selection (Optional) Filter used in the query.
  279 + * @param selectionArgs (Optional) Selection arguments used in the query.
  280 + * @return The value of the _data column, which is typically a file path.
  281 + */
  282 + private static String getDataColumn(Context context, Uri uri, String selection,
  283 + String[] selectionArgs) {
  284 + Cursor cursor = null;
  285 + final String column = "_data";
  286 + final String[] projection = {column};
  287 + try {
  288 + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
  289 + if (cursor != null && cursor.moveToFirst()) {
  290 + final int index = cursor.getColumnIndexOrThrow(column);
  291 + return cursor.getString(index);
  292 + }
  293 + } finally {
  294 + if (cursor != null)
  295 + cursor.close();
  296 + }
  297 + return null;
  298 + }
  299 +
  300 +
  301 + /**
  302 + * 判断外部存储是否可用
  303 + */
  304 + public static boolean isExternalStorageWritable() {
  305 + String state = Environment.getExternalStorageState();
  306 + if (Environment.MEDIA_MOUNTED.equals(state)) {
  307 + return true;
  308 + }
  309 + Log.e(TAG, "ExternalStorage not mounted");
  310 + return false;
  311 + }
  312 +
  313 + public static boolean isMediaDocument(Uri uri) {
  314 + return "com.android.providers.media.documents".equals(uri.getAuthority());
  315 + }
  316 +
  317 + public static boolean isExternalStorageDocument(Uri uri) {
  318 + return "com.android.externalstorage.documents".equals(uri.getAuthority());
  319 + }
  320 +
  321 + /**
  322 + * @param uri The Uri to check.
  323 + * @return Whether the Uri authority is DownloadsProvider.
  324 + */
  325 + public static boolean isDownloadsDocument(Uri uri) {
  326 + return "com.android.providers.downloads.documents".equals(uri.getAuthority());
  327 + }
  328 +
  329 +
  330 + public enum FileType {
  331 + IMG,
  332 + AUDIO,
  333 + VIDEO,
  334 + FILE,
  335 + }
  336 +
  337 +
  338 +}
app/src/main/java/com/cnlive/im/util/MediaUtil.java 0 → 100644
  1 +package com.cnlive.im.util;
  2 +
  3 +import android.media.MediaPlayer;
  4 +import android.net.Uri;
  5 +import android.util.Log;
  6 +
  7 +import com.cnlive.im.CNLiveApplication;
  8 +
  9 +import java.io.FileInputStream;
  10 +import java.io.IOException;
  11 +
  12 +/**
  13 + * 媒体播放工具
  14 + */
  15 +public class MediaUtil {
  16 +
  17 + private static final String TAG = "MediaUtil";
  18 +
  19 + private MediaPlayer player;
  20 + private EventListener eventListener;
  21 +
  22 + private MediaUtil() {
  23 + player = new MediaPlayer();
  24 + }
  25 +
  26 + private static MediaUtil instance = new MediaUtil();
  27 +
  28 + public static MediaUtil getInstance() {
  29 + return instance;
  30 + }
  31 +
  32 + public MediaPlayer getPlayer() {
  33 + return player;
  34 + }
  35 +
  36 +
  37 + public void setEventListener(final EventListener eventListener) {
  38 + if (player != null) {
  39 + player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
  40 + @Override
  41 + public void onCompletion(MediaPlayer mp) {
  42 + eventListener.onStop();
  43 + }
  44 + });
  45 + }
  46 + this.eventListener = eventListener;
  47 + }
  48 +
  49 + public void play(FileInputStream inputStream) {
  50 + try {
  51 + if (eventListener != null) {
  52 + eventListener.onStop();
  53 + }
  54 + player.reset();
  55 + player.setDataSource(inputStream.getFD());
  56 + player.prepare();
  57 + player.start();
  58 + } catch (IOException e) {
  59 + Log.e(TAG, "play error:" + e);
  60 + }
  61 +
  62 +
  63 + }
  64 +
  65 +
  66 + public void stop() {
  67 + if (player != null && player.isPlaying()) {
  68 + player.stop();
  69 + }
  70 + }
  71 +
  72 + public long getDuration(String path) {
  73 + player = MediaPlayer.create(CNLiveApplication.getContext(), Uri.parse(path));
  74 + return player.getDuration();
  75 + }
  76 +
  77 +
  78 + /**
  79 + * 播放器事件监听
  80 + */
  81 + public interface EventListener {
  82 + void onStop();
  83 + }
  84 +}
app/src/main/java/com/cnlive/im/util/MessageType.java
@@ -9,4 +9,5 @@ public class MessageType { @@ -9,4 +9,5 @@ public class MessageType {
9 public static final String stringMessage = "1"; 9 public static final String stringMessage = "1";
10 public static final String imaMessage = "2"; 10 public static final String imaMessage = "2";
11 public static final String voiceMessage = "3"; 11 public static final String voiceMessage = "3";
  12 + public static final String videoMessage = "4";
12 } 13 }
app/src/main/java/com/cnlive/im/util/PlayerUtil.java deleted 100644 → 0
1 -package com.cnlive.im.util;  
2 -  
3 -import android.content.Context;  
4 -import android.media.MediaPlayer;  
5 -import android.net.Uri;  
6 -  
7 -/**  
8 - * Created by Lynn on 2017/7/21.  
9 - */  
10 -  
11 -public class PlayerUtil implements IVoiceManager{  
12 - private final String TAG = "PlayerUtil";  
13 - private String path;  
14 - private Context mContext;  
15 -  
16 - private MediaPlayer mediaPlayer;  
17 -  
18 - public PlayerUtil(Context context){  
19 - this.mContext = context;  
20 -// mediaPlayer = new MediaPlayer();  
21 -// mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {  
22 -// @Override  
23 -// public void onCompletion(MediaPlayer mediaPlayer) {  
24 -//// mediaPlayer.stop();  
25 -// stop();  
26 -// }  
27 -// });  
28 - }  
29 -  
30 - @Override  
31 - public boolean start(Uri uri) {  
32 - try {  
33 - mediaPlayer = new MediaPlayer();  
34 - mediaPlayer.setOnCompletionListener(onCompletionListener);  
35 - mediaPlayer.setOnPreparedListener(onPreparedListener);  
36 - mediaPlayer.setDataSource(mContext, uri);  
37 - mediaPlayer.prepare();  
38 -// mediaPlayer.start();  
39 - }catch (Exception e){  
40 - e.printStackTrace();  
41 - }  
42 - return false;  
43 - }  
44 -  
45 - @Override  
46 - public boolean stop() {  
47 - mediaPlayer.stop();  
48 - mediaPlayer.release();  
49 - mediaPlayer = null;  
50 - return false;  
51 - }  
52 -  
53 - @Override  
54 - public void onDestory() {  
55 - mediaPlayer.release();  
56 - mediaPlayer = null;  
57 - }  
58 -  
59 - private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {  
60 - @Override  
61 - public void onCompletion(MediaPlayer mediaPlayer) {  
62 - stop();  
63 - }  
64 - };  
65 -  
66 - private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {  
67 - @Override  
68 - public void onPrepared(MediaPlayer mediaPlayer) {  
69 - mediaPlayer.start();  
70 - }  
71 - };  
72 -}  
app/src/main/jniLibs/arm64-v8a/libBugly.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/lib_imcore_group_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/lib_imcore_jni_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/lib_imcore_msg_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/lib_imcore_sns_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/lib_imcore_ugc_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/libgnustl_shared.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/libqalcodecwrapper.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/libqalmsfboot.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/libwtcrypto.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libBugly.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/lib_imcore_group_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/lib_imcore_jni_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/lib_imcore_msg_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/lib_imcore_sns_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/lib_imcore_ugc_ext_gyp.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libgnustl_shared.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libqalcodecwrapper.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libqalmsfboot.so 0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libwtcrypto.so 0 → 100644
No preview for this file type
app/src/main/res/drawable/left_voice.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<animation-list
  3 + android:oneshot="false"
  4 + xmlns:android="http://schemas.android.com/apk/res/android">
  5 + <item android:drawable="@drawable/left_voice3" android:duration="200" />
  6 + <item android:drawable="@drawable/left_voice1" android:duration="200" />
  7 + <item android:drawable="@drawable/left_voice2" android:duration="200" />
  8 + <item android:drawable="@drawable/left_voice3" android:duration="200" />
  9 +</animation-list>
0 \ No newline at end of file 10 \ No newline at end of file
app/src/main/res/drawable/left_voice1.png 0 → 100644

1.05 KB

app/src/main/res/drawable/left_voice2.png 0 → 100644

1.31 KB

app/src/main/res/drawable/left_voice3.png 0 → 100644

1.58 KB

app/src/main/res/drawable/right_voice.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<animation-list
  3 + android:oneshot="false"
  4 + xmlns:android="http://schemas.android.com/apk/res/android">
  5 + <item android:drawable="@drawable/right_voice3" android:duration="200" />
  6 + <item android:drawable="@drawable/right_voice1" android:duration="200" />
  7 + <item android:drawable="@drawable/right_voice2" android:duration="200" />
  8 + <item android:drawable="@drawable/right_voice3" android:duration="200" />
  9 +</animation-list>
0 \ No newline at end of file 10 \ No newline at end of file
app/src/main/res/drawable/right_voice1.png 0 → 100644

1.05 KB

app/src/main/res/drawable/right_voice2.png 0 → 100644

1.28 KB

app/src/main/res/drawable/right_voice3.png 0 → 100644

1.42 KB

app/src/main/res/drawable/voice_none_read.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +
  3 +<shape xmlns:android="http://schemas.android.com/apk/res/android"
  4 + android:shape="oval">
  5 + <solid android:color="#ff0000" />
  6 + <corners android:radius="10dp"/>
  7 + <stroke
  8 + android:width="1dp"
  9 + android:color="#8a8a8a" />
  10 +</shape>
0 \ No newline at end of file 11 \ No newline at end of file
app/src/main/res/layout/activity_groupchat.xml
@@ -117,6 +117,18 @@ @@ -117,6 +117,18 @@
117 android:layout_height="wrap_content" 117 android:layout_height="wrap_content"
118 android:text="退出" /> 118 android:text="退出" />
119 119
  120 + <Button
  121 + android:id="@+id/videoBtn"
  122 + android:layout_width="wrap_content"
  123 + android:layout_height="wrap_content"
  124 + android:text="视频文件"/>
  125 +
  126 + <Button
  127 + android:id="@+id/ugcVideoBtn"
  128 + android:layout_width="wrap_content"
  129 + android:layout_height="wrap_content"
  130 + android:text="短视频"/>
  131 +
120 </LinearLayout> 132 </LinearLayout>
121 133
122 </LinearLayout> 134 </LinearLayout>
app/src/main/res/layout/activity_image_view.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:background="@android:color/black"
  6 + android:orientation="vertical">
  7 +
  8 + <ImageView
  9 + android:id="@+id/image"
  10 + android:layout_width="match_parent"
  11 + android:layout_height="match_parent"
  12 + android:scaleType="centerInside" />
  13 +
  14 +</LinearLayout>
0 \ No newline at end of file 15 \ No newline at end of file
app/src/main/res/layout/activity_play.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical"
  6 + android:gravity="center">
  7 +
  8 + <VideoView
  9 + android:id="@+id/video"
  10 + android:layout_width="match_parent"
  11 + android:layout_height="match_parent" />
  12 +
  13 +</LinearLayout>
0 \ No newline at end of file 14 \ No newline at end of file
app/src/main/res/layout/activity_private_chat.xml
@@ -36,6 +36,18 @@ @@ -36,6 +36,18 @@
36 android:layout_height="wrap_content" 36 android:layout_height="wrap_content"
37 android:text="邀请对方聊天" /> 37 android:text="邀请对方聊天" />
38 38
  39 + <Button
  40 + android:id="@+id/videoBtn"
  41 + android:layout_width="wrap_content"
  42 + android:layout_height="wrap_content"
  43 + android:text="视频文件"/>
  44 +
  45 + <Button
  46 + android:id="@+id/ugcVideoBtn"
  47 + android:layout_width="wrap_content"
  48 + android:layout_height="wrap_content"
  49 + android:text="短视频"/>
  50 +
39 51
40 <LinearLayout 52 <LinearLayout
41 android:id="@+id/edit_layout_se" 53 android:id="@+id/edit_layout_se"
app/src/main/res/layout/imag_layout_item_oppsite.xml
@@ -17,15 +17,15 @@ @@ -17,15 +17,15 @@
17 android:layout_height="wrap_content" 17 android:layout_height="wrap_content"
18 android:layout_alignParentLeft="true" 18 android:layout_alignParentLeft="true"
19 android:layout_centerVertical="true" 19 android:layout_centerVertical="true"
20 - android:text="游客" /> 20 + android:text="游客"
  21 + android:textColor="#d61d0c" />
21 22
22 <ImageView 23 <ImageView
23 android:id="@+id/img_content" 24 android:id="@+id/img_content"
24 android:layout_width="40dp" 25 android:layout_width="40dp"
25 android:layout_height="40dp" 26 android:layout_height="40dp"
26 android:layout_marginLeft="5dp" 27 android:layout_marginLeft="5dp"
27 - android:layout_toRightOf="@+id/img_user_name"  
28 - android:src="@drawable/vod_detail_good_on" /> 28 + android:layout_toRightOf="@+id/img_user_name"/>
29 29
30 </RelativeLayout> 30 </RelativeLayout>
31 31
app/src/main/res/layout/imag_layout_item_user.xml
1 <?xml version="1.0" encoding="utf-8"?> 1 <?xml version="1.0" encoding="utf-8"?>
2 -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent" 3 android:layout_width="match_parent"
4 android:layout_height="match_parent" 4 android:layout_height="match_parent"
5 android:orientation="vertical" 5 android:orientation="vertical"
6 android:paddingBottom="10dp" 6 android:paddingBottom="10dp"
7 android:paddingTop="10dp"> 7 android:paddingTop="10dp">
8 8
9 - <RelativeLayout 9 + <LinearLayout
10 android:layout_width="wrap_content" 10 android:layout_width="wrap_content"
11 - android:layout_height="wrap_content"> 11 + android:layout_height="wrap_content"
  12 + android:layout_alignParentRight="true"
  13 + android:orientation="horizontal">
12 14
13 <TextView 15 <TextView
14 - android:layout_centerVertical="true"  
15 - android:id="@+id/img_user_name" 16 + android:id="@+id/status"
16 android:layout_width="wrap_content" 17 android:layout_width="wrap_content"
17 android:layout_height="wrap_content" 18 android:layout_height="wrap_content"
18 - android:layout_alignParentRight="true"  
19 - android:text="游客" /> 19 + android:layout_gravity="center_vertical"
  20 + android:layout_marginRight="5dp"
  21 + android:gravity="right"
  22 + android:textColor="@android:color/holo_blue_light" />
20 23
21 <ImageView 24 <ImageView
22 - android:layout_toLeftOf="@+id/img_user_name"  
23 - android:layout_marginRight="5dp"  
24 android:id="@+id/img_content" 25 android:id="@+id/img_content"
25 android:layout_width="40dp" 26 android:layout_width="40dp"
26 android:layout_height="40dp" 27 android:layout_height="40dp"
27 - android:src="@drawable/vod_detail_good_on"/> 28 + android:layout_marginRight="5dp" />
  29 +
  30 + <TextView
  31 + android:id="@+id/img_user_name"
  32 + android:layout_width="wrap_content"
  33 + android:layout_height="wrap_content"
  34 + android:layout_gravity="center_vertical"
  35 + android:text="游客"
  36 + android:textColor="#d61d0c"/>
28 37
29 - </RelativeLayout> 38 + </LinearLayout>
30 39
31 -</LinearLayout>  
32 \ No newline at end of file 40 \ No newline at end of file
  41 +</RelativeLayout>
33 \ No newline at end of file 42 \ No newline at end of file
app/src/main/res/layout/string_layout_item_oppsite.xml
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 android:layout_width="wrap_content" 3 android:layout_width="wrap_content"
4 android:layout_height="wrap_content" 4 android:layout_height="wrap_content"
5 android:orientation="vertical" 5 android:orientation="vertical"
6 - android:paddingTop="10dp"  
7 - android:paddingBottom="10dp"> 6 + android:paddingBottom="10dp"
  7 + android:paddingTop="10dp">
8 8
9 <RelativeLayout 9 <RelativeLayout
10 android:id="@+id/re_chat_room" 10 android:id="@+id/re_chat_room"
@@ -24,11 +24,12 @@ @@ -24,11 +24,12 @@
24 android:id="@+id/msg_text" 24 android:id="@+id/msg_text"
25 android:layout_width="wrap_content" 25 android:layout_width="wrap_content"
26 android:layout_height="wrap_content" 26 android:layout_height="wrap_content"
  27 + android:layout_marginLeft="5dp"
27 android:layout_toRightOf="@id/user_name" 28 android:layout_toRightOf="@id/user_name"
28 android:text="vfgfgf" 29 android:text="vfgfgf"
29 android:textColor="@android:color/black" 30 android:textColor="@android:color/black"
30 - android:textSize="15sp"  
31 - android:layout_marginLeft="5dp"/> 31 + android:textSize="15sp" />
  32 +
32 </RelativeLayout> 33 </RelativeLayout>
33 34
34 </RelativeLayout> 35 </RelativeLayout>
35 \ No newline at end of file 36 \ No newline at end of file
app/src/main/res/layout/string_layout_item_user.xml
@@ -5,31 +5,43 @@ @@ -5,31 +5,43 @@
5 android:paddingBottom="10dp" 5 android:paddingBottom="10dp"
6 android:paddingTop="10dp"> 6 android:paddingTop="10dp">
7 7
8 - <RelativeLayout 8 + <LinearLayout
9 android:id="@+id/re_chat_room" 9 android:id="@+id/re_chat_room"
10 android:layout_width="wrap_content" 10 android:layout_width="wrap_content"
11 - android:layout_height="wrap_content"> 11 + android:layout_height="wrap_content"
  12 + android:layout_alignParentRight="true"
  13 + android:orientation="horizontal">
12 14
13 <TextView 15 <TextView
14 - android:id="@+id/user_name" 16 + android:id="@+id/status"
15 android:layout_width="wrap_content" 17 android:layout_width="wrap_content"
16 android:layout_height="wrap_content" 18 android:layout_height="wrap_content"
17 - android:layout_alignParentRight="true"  
18 - android:gravity="center_vertical"  
19 - android:text="ddd"  
20 - android:textColor="#d61d0c"  
21 - android:textSize="14sp" /> 19 + android:layout_gravity="center_vertical"
  20 + android:layout_marginRight="5dp"
  21 + android:gravity="right"
  22 + android:textColor="@android:color/holo_blue_light" />
22 23
23 <TextView 24 <TextView
24 android:id="@+id/msg_text" 25 android:id="@+id/msg_text"
25 android:layout_width="wrap_content" 26 android:layout_width="wrap_content"
26 android:layout_height="wrap_content" 27 android:layout_height="wrap_content"
27 - android:layout_toLeftOf="@id/user_name" 28 +
  29 + android:layout_marginRight="5dp"
28 android:text="vfgfgf" 30 android:text="vfgfgf"
29 android:textColor="@android:color/black" 31 android:textColor="@android:color/black"
30 - android:textSize="15sp"  
31 - android:layout_marginRight="5dp"/>  
32 - </RelativeLayout> 32 + android:textSize="15sp" />
  33 +
  34 + <TextView
  35 + android:id="@+id/user_name"
  36 + android:layout_width="wrap_content"
  37 + android:layout_height="wrap_content"
  38 + android:layout_gravity="right"
  39 + android:gravity="center_vertical"
  40 + android:text="ddd"
  41 + android:textColor="#d61d0c"
  42 + android:textSize="14sp" />
  43 +
  44 + </LinearLayout>
33 45
34 46
35 </RelativeLayout> 47 </RelativeLayout>
36 \ No newline at end of file 48 \ No newline at end of file
app/src/main/res/layout/video_layout_item_oppsite.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical"
  6 + android:paddingBottom="10dp"
  7 + android:paddingTop="10dp">
  8 +
  9 +
  10 + <RelativeLayout
  11 + android:layout_width="wrap_content"
  12 + android:layout_height="wrap_content">
  13 +
  14 + <TextView
  15 + android:id="@+id/user_name"
  16 + android:layout_width="wrap_content"
  17 + android:layout_height="wrap_content"
  18 + android:layout_alignParentLeft="true"
  19 + android:layout_centerVertical="true"
  20 + android:layout_margin="5dp"
  21 + android:text="游客"
  22 + android:textColor="#d61d0c" />
  23 +
  24 + <RelativeLayout
  25 + android:id="@+id/videoLayout"
  26 + android:layout_width="100dp"
  27 + android:layout_height="150dp"
  28 + android:layout_toRightOf="@+id/user_name">
  29 +
  30 + <ImageView
  31 + android:id="@+id/img_content"
  32 + android:layout_width="100dp"
  33 + android:layout_height="150dp"
  34 + android:layout_marginLeft="5dp"
  35 + android:scaleType="centerInside"
  36 + android:src="@drawable/vod_detail_good_on" />
  37 +
  38 + <ImageView
  39 + android:layout_width="30dp"
  40 + android:layout_height="30dp"
  41 + android:layout_centerInParent="true"
  42 + android:src="@android:drawable/ic_media_play" />
  43 +
  44 + </RelativeLayout>
  45 +
  46 + </RelativeLayout>
  47 +
  48 +</LinearLayout>
0 \ No newline at end of file 49 \ No newline at end of file
app/src/main/res/layout/video_layout_item_user.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:orientation="vertical"
  6 + android:paddingBottom="10dp"
  7 + android:paddingTop="10dp">
  8 +
  9 + <LinearLayout
  10 + android:layout_width="wrap_content"
  11 + android:layout_height="wrap_content"
  12 + android:orientation="horizontal"
  13 + android:layout_alignParentRight="true">
  14 +
  15 + <TextView
  16 + android:id="@+id/status"
  17 + android:layout_width="wrap_content"
  18 + android:layout_height="wrap_content"
  19 + android:layout_gravity="center_vertical"
  20 + android:layout_marginRight="5dp"
  21 + android:gravity="right"
  22 + android:textColor="@android:color/holo_blue_light" />
  23 +
  24 + <RelativeLayout
  25 + android:id="@+id/videoLayout"
  26 + android:layout_width="100dp"
  27 + android:layout_height="150dp"
  28 + android:layout_toLeftOf="@+id/user_name">
  29 +
  30 + <ImageView
  31 + android:id="@+id/img_content"
  32 + android:layout_width="100dp"
  33 + android:layout_height="150dp"
  34 + android:layout_marginRight="5dp"
  35 + android:scaleType="centerInside"
  36 + android:src="@drawable/vod_detail_good_on" />
  37 +
  38 + <ImageView
  39 + android:layout_width="30dp"
  40 + android:layout_height="30dp"
  41 + android:layout_centerInParent="true"
  42 + android:src="@android:drawable/ic_media_play" />
  43 +
  44 + </RelativeLayout>
  45 +
  46 + <TextView
  47 + android:id="@+id/user_name"
  48 + android:layout_width="wrap_content"
  49 + android:layout_height="wrap_content"
  50 + android:layout_gravity="center_vertical"
  51 + android:layout_margin="5dp"
  52 + android:text="游客"
  53 + android:textColor="#d61d0c" />
  54 +
  55 + </LinearLayout>
  56 +
  57 +</RelativeLayout>
0 \ No newline at end of file 58 \ No newline at end of file
app/src/main/res/layout/voice_layout_item_oppsite.xml
@@ -16,15 +16,26 @@ @@ -16,15 +16,26 @@
16 android:layout_height="wrap_content" 16 android:layout_height="wrap_content"
17 android:layout_alignParentLeft="true" 17 android:layout_alignParentLeft="true"
18 android:layout_centerVertical="true" 18 android:layout_centerVertical="true"
19 - android:text="游客" /> 19 + android:text="游客"
  20 + android:textColor="#d61d0c" />
20 21
21 - <TextView 22 + <RelativeLayout
22 android:id="@+id/voice_content" 23 android:id="@+id/voice_content"
23 - android:layout_width="wrap_content"  
24 - android:layout_height="50dp" 24 + android:layout_width="71dp"
  25 + android:layout_height="48dp"
  26 + android:layout_marginLeft="5dp"
25 android:layout_toRightOf="@+id/voice_user_name" 27 android:layout_toRightOf="@+id/voice_user_name"
26 - android:background="@drawable/voice_bg_left"  
27 - android:layout_marginLeft="5dp"/> 28 + android:background="@drawable/voice_bg_left">
  29 +
  30 + <ImageView
  31 + android:id="@+id/voiceAnim"
  32 + android:layout_width="11dp"
  33 + android:layout_height="17dp"
  34 + android:layout_centerVertical="true"
  35 + android:layout_marginLeft="10dp"
  36 + android:background="@drawable/left_voice" />
  37 +
  38 + </RelativeLayout>
28 39
29 <TextView 40 <TextView
30 android:id="@+id/voice_duration" 41 android:id="@+id/voice_duration"
@@ -33,6 +44,15 @@ @@ -33,6 +44,15 @@
33 android:layout_centerVertical="true" 44 android:layout_centerVertical="true"
34 android:layout_toRightOf="@id/voice_content" /> 45 android:layout_toRightOf="@id/voice_content" />
35 46
  47 + <View
  48 + android:id="@+id/noneRead"
  49 + android:layout_width="10dp"
  50 + android:layout_height="10dp"
  51 + android:layout_centerVertical="true"
  52 + android:layout_marginLeft="2dp"
  53 + android:layout_toRightOf="@+id/voice_duration"
  54 + android:background="@drawable/voice_none_read" />
  55 +
36 56
37 </RelativeLayout> 57 </RelativeLayout>
38 58
app/src/main/res/layout/voice_layout_item_user.xml
@@ -5,33 +5,52 @@ @@ -5,33 +5,52 @@
5 android:paddingBottom="10dp" 5 android:paddingBottom="10dp"
6 android:paddingTop="10dp"> 6 android:paddingTop="10dp">
7 7
8 - <RelativeLayout 8 + <LinearLayout
9 android:layout_width="wrap_content" 9 android:layout_width="wrap_content"
10 - android:layout_height="wrap_content"> 10 + android:layout_height="wrap_content"
  11 + android:layout_alignParentRight="true">
11 12
12 <TextView 13 <TextView
13 - android:id="@+id/voice_user_name" 14 + android:id="@+id/status"
14 android:layout_width="wrap_content" 15 android:layout_width="wrap_content"
15 android:layout_height="wrap_content" 16 android:layout_height="wrap_content"
16 - android:layout_alignParentRight="true"  
17 - android:layout_centerVertical="true"  
18 - android:text="游客" /> 17 + android:layout_gravity="center_vertical"
  18 + android:layout_marginRight="5dp"
  19 + android:gravity="right"
  20 + android:textColor="@android:color/holo_blue_light" />
19 21
20 <TextView 22 <TextView
21 - android:id="@+id/voice_content" 23 + android:id="@+id/voice_duration"
22 android:layout_width="wrap_content" 24 android:layout_width="wrap_content"
23 - android:layout_height="50dp"  
24 - android:layout_toLeftOf="@+id/voice_user_name"  
25 - android:background="@drawable/voice_bg_right"  
26 - android:layout_marginRight="5dp"/> 25 + android:layout_height="wrap_content"
  26 + android:layout_gravity="center_vertical" />
  27 +
  28 + <RelativeLayout
  29 + android:id="@+id/voice_content"
  30 + android:layout_width="71dp"
  31 + android:layout_height="48dp"
  32 + android:layout_marginRight="5dp"
  33 + android:background="@drawable/voice_bg_right">
  34 +
  35 + <ImageView
  36 + android:id="@+id/voiceAnim"
  37 + android:layout_width="11dp"
  38 + android:layout_height="17dp"
  39 + android:layout_alignParentRight="true"
  40 + android:layout_centerVertical="true"
  41 + android:layout_marginRight="10dp"
  42 + android:background="@drawable/right_voice" />
  43 +
  44 + </RelativeLayout>
27 45
28 <TextView 46 <TextView
29 - android:id="@+id/voice_duration" 47 + android:id="@+id/voice_user_name"
30 android:layout_width="wrap_content" 48 android:layout_width="wrap_content"
31 android:layout_height="wrap_content" 49 android:layout_height="wrap_content"
32 - android:layout_centerVertical="true"  
33 - android:layout_toLeftOf="@id/voice_content" /> 50 + android:layout_gravity="center_vertical"
  51 + android:text="游客"
  52 + android:textColor="#d61d0c" />
34 53
35 - </RelativeLayout> 54 + </LinearLayout>
36 55
37 </RelativeLayout> 56 </RelativeLayout>
38 \ No newline at end of file 57 \ No newline at end of file