OSDN Git Service

video
authoryg <yg2010.6.11@qq.com>
Mon, 5 Dec 2016 03:16:55 +0000 (11:16 +0800)
committeryg <yg2010.6.11@qq.com>
Mon, 5 Dec 2016 03:16:55 +0000 (11:16 +0800)
42 files changed:
.idea/inspectionProfiles/Project_Default.xml
app/src/main/AndroidManifest.xml
app/src/main/java/cc/minsnail/activity/ChatActivity.java
app/src/main/java/cc/minsnail/activity/MainActivity.java
app/src/main/java/cc/minsnail/activity/RegisterActivity.java
app/src/main/java/cc/minsnail/activity/SearchUserActivity.java
app/src/main/java/cc/minsnail/activity/UserDetailsActivity.java
app/src/main/java/cc/minsnail/activity/UserInfoActivity.java
app/src/main/java/cc/minsnail/adapter/ChatAdapter.java
app/src/main/java/cc/minsnail/adapter/FriendsAdapter.java
app/src/main/java/cc/minsnail/adapter/MessageAdapter.java
app/src/main/java/cc/minsnail/beans/YgInfo.java
app/src/main/java/cc/minsnail/beans/YgMessage.java
app/src/main/java/cc/minsnail/beans/YgText.java
app/src/main/java/cc/minsnail/beans/YgTreeNode.java
app/src/main/java/cc/minsnail/beans/YgUser.java
app/src/main/java/cc/minsnail/beans/YgUserConfig.java
app/src/main/java/cc/minsnail/beans/YgUserIQ.java
app/src/main/java/cc/minsnail/beans/YgVCard.java
app/src/main/java/cc/minsnail/config/Config.java
app/src/main/java/cc/minsnail/fragment/MessageFragment.java
app/src/main/java/cc/minsnail/fragment/RosterFragment.java
app/src/main/java/cc/minsnail/manager/AudioRecorderManager.java [moved from app/src/main/java/cc/minsnail/manager/AudioManager.java with 56% similarity]
app/src/main/java/cc/minsnail/manager/DialogManager.java
app/src/main/java/cc/minsnail/manager/MediaManager.java [deleted file]
app/src/main/java/cc/minsnail/manager/MediaPlayerManager.java [new file with mode: 0644]
app/src/main/java/cc/minsnail/manager/OssManager.java
app/src/main/java/cc/minsnail/receiver/MsgReceiver.java
app/src/main/java/cc/minsnail/service/ClientService.java
app/src/main/java/cc/minsnail/service/SmackService.java
app/src/main/java/cc/minsnail/tools/SharedHelper.java
app/src/main/java/cc/minsnail/tools/TreeHelper.java
app/src/main/java/cc/minsnail/tools/Utils.java
app/src/main/java/cc/minsnail/view/AudioRecordeButton.java
app/src/main/res/layout/activity_chat.xml
app/src/main/res/layout/chat_pic_item_1.xml
app/src/main/res/layout/chat_pic_item_2.xml
app/src/main/res/layout/chat_txt_item_2.xml
app/src/main/res/mipmap-hdpi/ic_menu_back.png [new file with mode: 0644]
app/src/main/res/mipmap-hdpi/video_camera.png [new file with mode: 0644]
app/src/main/res/mipmap-mdpi/video_camera.png [new file with mode: 0644]
app/src/main/res/values/strings.xml

index 3b5f215..8209e02 100644 (file)
@@ -1,6 +1,11 @@
 <component name="InspectionProjectProfileManager">
   <profile version="1.0">
     <option name="myName" value="Project Default" />
+    <inspection_tool class="AndroidLintDuplicateIds" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintValidFragment" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
+      <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
+      <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
+    </inspection_tool>
   </profile>
 </component>
\ No newline at end of file
index f855c13..71a124f 100644 (file)
@@ -3,9 +3,9 @@
     package="cc.minsnail.smackclient">
 
     <!-- To auto-complete the email text field in the login form with the user's emails -->
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-    <uses-permission android:name="android.permission.READ_PROFILE" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS"></uses-permission>
+    <uses-permission android:name="android.permission.READ_PROFILE"></uses-permission>
+    <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
     <uses-permission android:name="android.permission.CAMERA"></uses-permission>
     <uses-permission android:name="android.permission.INTERNET"></uses-permission>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
     <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    <uses-feature
+        android:name="android.hardware.camera"
+        android:required="true"></uses-feature>
+    <uses-feature android:name="android.hardware.location.gps"></uses-feature>
 
     <application
         android:allowBackup="true"
         android:icon="@mipmap/chat_icon"
         android:label="@string/app_name"
-        android:supportsRtl="true"
-        android:theme="@style/Theme.AppCompat.Light.NoActionBar"
         android:persistent="true"
-        >
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppCompat.Light.NoActionBar">
         <activity
             android:name="cc.minsnail.activity.LoginActivity"
             android:label="@string/app_name"
@@ -54,7 +60,8 @@
 
             </meta-data>
         </activity>
-        <activity android:name="cc.minsnail.activity.SearchUserActivity"
+        <activity
+            android:name="cc.minsnail.activity.SearchUserActivity"
             android:parentActivityName="cc.minsnail.activity.MainActivity"
             android:screenOrientation="nosensor">
             <intent-filter>
@@ -62,8 +69,7 @@
             </intent-filter>
             <meta-data
                 android:name="android.support.PARENT_ACTIVITY"
-                android:value="cc.minsnail.activity.MainActivity">
-            </meta-data>
+                android:value="cc.minsnail.activity.MainActivity"></meta-data>
         </activity>
         <activity
             android:name="cc.minsnail.activity.UserInfoActivity"
                 <category android:name="android.intent.category.LAUNCHER"></category>
             </intent-filter>
         </activity>
-        <activity android:name="cc.minsnail.activity.RegisterActivity"
+        <activity
+            android:name="cc.minsnail.activity.RegisterActivity"
             android:screenOrientation="nosensor">
             <intent-filter>
                 <category android:name="android.intent.category.LAUNCHER"></category>
             </intent-filter>
         </activity>
-        <activity android:name="cc.minsnail.activity.UserDetailsActivity"
+        <activity
+            android:name="cc.minsnail.activity.UserDetailsActivity"
             android:screenOrientation="nosensor">
             <intent-filter>
                 <category android:name="android.intent.category.LAUNCHER"></category>
                 <category android:name="android.intent.category.LAUNCHER"></category>
             </intent-filter>
         </activity>
+        <activity android:name="cc.minsnail.activity.VideoPreviewWindowActivity"></activity>
+
         <service
             android:name="cc.minsnail.service.SmackService"
-            android:process=":SmackService"
-            android:enabled="true">
+            android:enabled="true"
+            android:process=":SmackService">
             <intent-filter>
                 <action android:name="android.intent.action.SMACK_CLIENT_SERVICE"></action>
             </intent-filter>
         </service>
+        <service android:name="cc.minsnail.service.ClientService"></service>
+
         <receiver android:name="cc.minsnail.receiver.MsgReceiver">
             <intent-filter android:priority="100">
                 <action android:name="MsgRecerver"></action>
index 98c13bb..c52c1f0 100644 (file)
@@ -1,5 +1,8 @@
 package cc.minsnail.activity;
 
+import android.animation.ValueAnimator;
+import android.annotation.TargetApi;
+import android.app.FragmentTransaction;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -9,16 +12,19 @@ import android.content.ServiceConnection;
 import android.graphics.drawable.AnimationDrawable;
 import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.app.FragmentManager;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
-import android.system.Os;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -27,7 +33,9 @@ import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ImageButton;
+import android.widget.LinearLayout;
 import android.widget.ListView;
+import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -47,12 +55,14 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import cc.minsnail.Contents;
 import cc.minsnail.adapter.ChatAdapter;
 import cc.minsnail.beans.ChatMessageItem;
 import cc.minsnail.beans.YgText;
 import cc.minsnail.config.Config;
 import cc.minsnail.database.DataBaseManager;
-import cc.minsnail.manager.MediaManager;
+import cc.minsnail.fragment.VidewPreviewDialog;
+import cc.minsnail.manager.MediaPlayerManager;
 import cc.minsnail.manager.OssManager;
 import cc.minsnail.smackclient.R;
 import cc.minsnail.tools.SharedHelper;
@@ -61,15 +71,29 @@ import cc.minsnail.view.AudioRecordeButton;
 import cc.minsnail.beans.YgInfo;
 import cc.minsnail.beans.YgMessage;
 import cc.minsnail.aidl.IServiceAidlInterface;
+import cc.minsnail.view.ChatSurfaceView;
 import cc.minsnail.view.ImagePopupWindow;
 
 /**
  * Created by yg on 2016/9/23.
  */
 public class ChatActivity extends AppCompatActivity {
-    private static final int EORROR = 0;
-    private static final int SEND_TEXT_CHAT = 1;
-    private static final int AUDIO_FINISH_RECORDER = 2;
+    private static final int WHAT_EORROR = 0;
+    private static final int WHAT_SEND_TEXT = 1;
+    private static final int WHAT_AUDIO_FINISH_RECORDER = 2;
+    private static final int WHAT_SHOW_IMAGE = 3;
+    private static final int WHAT_DOWNLOAD_IMAGE = 4;
+    private static final int WHAT_DOWNLOAD_VIDEO = 5;
+    private static final int WHAT_SEND_IMAGE = 6;
+    private static final int WHAT_SEND_VIDEO = 7;
+    private static final int WHAT_SHOW_VIDEO = 8;
+
+    private static final int INTENT_REQUEST_IMAGE_CAPTURE = 1;
+    private static final int INTENT_REQUEST_VIDEO_CAPTURE = 2;
+
+    private static final String KEY_CHAT_POSITION = "position";
+    private static final String KEY_CHAT_IMAGE_PATH = "filePath";
+
     private static final String TAG = "ChatActivity";
     private SharedHelper mSharedHelper;
     //聊天对方用户
@@ -80,8 +104,11 @@ public class ChatActivity extends AppCompatActivity {
     private ImageButton mPhotoBtn;
     //发送语言按钮
     private ImageButton mAudioBtn;
+    private ImageButton mVideoBtn;
     //消息形式子菜单
     private RelativeLayout mSubMenus;
+    //聊天窗口底部工具
+    private LinearLayout mChatBottomBar;
     //录音窗口
     private RelativeLayout mRecordWindow;
     //发送文本窗口
@@ -106,9 +133,8 @@ public class ChatActivity extends AppCompatActivity {
     private MsgRecervier mMsgRecervier;
     //语音播放动画
     private View mAnimView;
-
+    //tool bar
     private Toolbar mToolbar;
-
     //登录用户jid
     private String mToJid;
     private String mToUserName;
@@ -117,31 +143,119 @@ public class ChatActivity extends AppCompatActivity {
     private String mFromJid;
     private String mFromUserName;
     private String mFromName;
-
+    //sqlite 操作对象
     private DataBaseManager mDataBaseManager;
-
+    //聊天窗口中是否有新加入的消息 便于更新聊天主窗口
     private boolean haveNews = false;
+    //阿里云 对象存储操作管理对象
     private OssManager mOssManger;
+    //图片消息点击事件(放大图片)
+    private OnImageClickListener mOnImageClickListener;
+    //图片放大弹出窗口
     private ImagePopupWindow mImagePopupWindow;
+    //屏幕密度
+    private int mDensityDpi;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_chat);
+        mToolbar = (Toolbar) findViewById(R.id.toolbar);
+        setSupportActionBar(mToolbar);
+        //tool bar 添加向上按钮
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(true);
+        //设置title
+        setTitle("");
+        //初始化 视图
+        initView();
+
+        //获取聊天双方信息
+        mToUserName = mSharedHelper.get(Config.KEY_TO_USERNAME, "admin");
+        mToJid = mToUserName;
+
+        mFromName = getIntent().getStringExtra(Config.KEY_FROM_NAME);
+        mFromNameView.setText(mFromName == null ? mFromUserName : mFromName);
+        mFromJid = getIntent().getStringExtra(Config.KEY_FROM_JID);
+        mFromUserName = mFromJid.split("@")[0];
+        //绑定后台服务
+        mConn = new ServiceConn();
+        Intent intent = new Intent("android.intent.action.SMACK_CLIENT_SERVICE");
+        intent.setPackage("cc.minsnail.www.smackclient");
+        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
+        mOnImageClickListener = new OnImageClickListener();
+        //初始化适配器
+        mChatAdapter = new ChatAdapter(ChatActivity.this, mDataBaseManager.queryChatMessageItems(mToUserName, mFromUserName), mChatBox);
+        mChatAdapter.setOnAudioClickListener(new OnAudioClickListener());
+        mChatAdapter.setOnImageClickListener(mOnImageClickListener);
+        mChatAdapter.setOnVideoClickListener(new OnVideoClickListener());
+        mChatAdapter.setOnVideoDoubleClickListener(new OnVideoDoubleClickListener());
+
+        mChatBox.setAdapter(mChatAdapter);
+        mChatBox.setSelection(mChatAdapter.getCount() - 1);
+        if (getIntent().getParcelableExtra(Config.KEY_MESSAGE) != null) {
+            mChatAdapter.addChat(new ChatMessageItem((YgMessage) getIntent().getParcelableExtra(Config.KEY_MESSAGE)));
+        }
+        //注册消息接收器
+        mMsgRecervier = new MsgRecervier();
+        IntentFilter intentFilter = new IntentFilter("MsgRecerver");
+        intentFilter.setPriority(1000);
+        registerReceiver(mMsgRecervier, intentFilter);
+        //绑定事件
+        event();
+        //初始化 阿里云对象存储 操作管理对象
+        mOssManger = OssManager.getInstance(ChatActivity.this);
+    }
+
+    //自定义反馈信息对象
     private YgInfo ygInfo;
+    //消息统一文本表示对象
     private YgText ygText = new YgText();
     private Handler handler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case SEND_TEXT_CHAT:
+                //文本消息发送成功
+                case WHAT_SEND_TEXT:
                     textSent();
                     break;
-                case AUDIO_FINISH_RECORDER:
-                    audioFinished();
+
+                //音频录音完成发送
+                case WHAT_AUDIO_FINISH_RECORDER:
+                    audioFinishedRecorder();
+                    break;
+
+                case WHAT_SEND_IMAGE:
+                    changeImageStatus(msg.arg1);
+                    break;
+
+                case WHAT_DOWNLOAD_IMAGE:
+                    OSSDownloadImage((ChatMessageItem) msg.obj);
+                    break;
+
+                case WHAT_SHOW_IMAGE:
+                    Bundle bundle = msg.getData();
+                    showReceivedImage(bundle.getInt(KEY_CHAT_POSITION), bundle.getString(KEY_CHAT_IMAGE_PATH), (ChatMessageItem) msg.obj);
+                    break;
+
+                case WHAT_SEND_VIDEO:
+                    changeLocalVideoStatus(msg.arg1);
+                    break;
+                case WHAT_DOWNLOAD_VIDEO:
+                    OSSDownloadVideo((ChatMessageItem) msg.obj);
                     break;
-                case EORROR:
+                case WHAT_SHOW_VIDEO:
+                    // TODO: 2016/11/30 显示视频消息
+                    showRecervedVideo((ChatMessageItem) msg.obj);
+                    break;
+                case WHAT_EORROR:
                     Toast.makeText(ChatActivity.this, ygInfo.getBody(), Toast.LENGTH_SHORT).show();
                     break;
             }
         }
     };
 
+    //文本消息发送成功后本地处理 显示与保存
     private void textSent() {
         YgMessage ygMessage = new YgMessage();
         ygMessage.setTo(mToJid);
@@ -149,13 +263,14 @@ public class ChatActivity extends AppCompatActivity {
         ygMessage.setBody(ygText.toJson());
         ygMessage.setCustom(1);
         mChatAdapter.addChat(new ChatMessageItem(ygMessage));
-        mChatBox.setSelection(mChatAdapter.getCount() - 1);
+        //mChatBox.setSelection(mChatAdapter.getCount() - 1);
         haveNews = true;
         mContent.setText("");
         Log.d(TAG, "send success");
     }
 
-    private void audioFinished() {
+    //音频消息发送成功后本地处理 显示与保存
+    private void audioFinishedRecorder() {
         YgMessage ygMessage = new YgMessage();
         ygMessage.setCustom(1);
         ygMessage.setBody(ygText.toJson());
@@ -166,48 +281,43 @@ public class ChatActivity extends AppCompatActivity {
         haveNews = true;
     }
 
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_chat);
-        mToolbar = (Toolbar) findViewById(R.id.toolbar);
-        setSupportActionBar(mToolbar);
-        ActionBar actionBar = getSupportActionBar();
-        actionBar.setDisplayHomeAsUpEnabled(true);
-        //设置title
-        setTitle("");
-        initView();
+    private void changeImageStatus(int position) {
+        int visiblePosition = mChatBox.getFirstVisiblePosition();
+        int index = position - visiblePosition;
+        if (index >= 0) {
+            View view = mChatBox.getChildAt(index);
+            ChatAdapter.PicHolderR picHolderR = (ChatAdapter.PicHolderR) view.getTag();
+            mChatBox.setAnimation(null);
+            picHolderR.progressBar.setVisibility(ProgressBar.INVISIBLE);
+        }
+    }
 
-        //信息窗消
-        mToUserName = mSharedHelper.get(Config.KEY_TO_USERNAME, "admin");
-        mToJid = mToUserName;
+    private void showReceivedImage(int position, String filePath, ChatMessageItem item) {
+//        int visiblePosition = mChatBox.getFirstVisiblePosition();
+//        int index = position - visiblePosition;
+//        if (index >= 0) {
+//            Log.i(TAG,"receive index:"+index);
+//            View view = mChatBox.getChildAt(index);
+//            ChatAdapter.PicHolderL picHolderL = (ChatAdapter.PicHolderL) view.getTag();
+//            picHolderL.pic.setTag(R.id.TAG_IMAGE_FILE_PATH,filePath);
+//            //picHolderL.progressBar.setVisibility(ProgressBar.INVISIBLE);
+//            picHolderL.pic.setImageFile(filePath);
+//            //picHolderL.pic.setImageResource(R.mipmap.ic_launcher);
+//            Log.i(TAG,"receive end");
+//        }
+        mChatAdapter.addChat(item);
+        mChatBox.setSelection(mChatAdapter.getCount() - 1);
+    }
 
-        mFromName = getIntent().getStringExtra(Config.KEY_FROM_NAME);
-        mFromNameView.setText(mFromName == null ? mFromUserName : mFromName);
-        mFromJid = getIntent().getStringExtra(Config.KEY_FROM_JID);
-        mFromUserName = mFromJid.split("@")[0];
-        //绑定后台服务
-        mConn = new ServiceConn();
-        Intent intent = new Intent("android.intent.action.SMACK_CLIENT_SERVICE");
-        intent.setPackage("cc.minsnail.www.smackclient");
-        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
+    private void changeLocalVideoStatus(int position) {
 
-        //初始化适配器
-        mChatAdapter = new ChatAdapter(ChatActivity.this, mDataBaseManager.queryChatMessageItems(mToUserName, mFromUserName), new OnAudioClickListener(), new OnImageClickListener());
-        mChatBox.setAdapter(mChatAdapter);
-        mChatBox.setSelection(mChatAdapter.getCount() - 1);
-        if (getIntent().getParcelableExtra(Config.KEY_MESSAGE) != null) {
-            mChatAdapter.addChat(new ChatMessageItem((YgMessage) getIntent().getParcelableExtra(Config.KEY_MESSAGE)));
-        }
-        //注册消息接收器
-        mMsgRecervier = new MsgRecervier();
-        IntentFilter intentFilter = new IntentFilter("MsgRecerver");
-        intentFilter.setPriority(1000);
-        registerReceiver(mMsgRecervier, intentFilter);
-        //绑定事件
-        event();
+    }
 
-        mOssManger = OssManager.getInstance(ChatActivity.this);
+    private void showRecervedVideo(ChatMessageItem item) {
+        // TODO: 2016/11/30
+        mChatAdapter.addChat(item);
+        mChatBox.setSelection(mChatAdapter.getCount() - 1);
+        haveNews = true;
     }
 
     private void initView() {
@@ -217,26 +327,29 @@ public class ChatActivity extends AppCompatActivity {
         mContent = (EditText) findViewById(R.id.content);
         mMoreBtn = (ImageButton) findViewById(R.id.more);
         mSubMenus = (RelativeLayout) findViewById(R.id.subMenus);
-        mPhotoBtn = (ImageButton) findViewById(R.id.sendPic);
-        mAudioBtn = (ImageButton) findViewById(R.id.audio);
+        mChatBottomBar = (LinearLayout) findViewById(R.id.chat_bottom_bar);
+        mPhotoBtn = (ImageButton) findViewById(R.id.submenu_pic_btn);
+        mAudioBtn = (ImageButton) findViewById(R.id.submenu_audio_btn);
+        mVideoBtn = (ImageButton) findViewById(R.id.submenu_video_btn);
         mChangeBtn = (ImageButton) findViewById(R.id.chanage);
         mRecordWindow = (RelativeLayout) findViewById(R.id.sendAudio);
         mTextWindow = (RelativeLayout) findViewById(R.id.sendText);
         mAudioRecorderButton = (AudioRecordeButton) findViewById(R.id.recorder_button);
-        mSharedHelper = new SharedHelper(ChatActivity.this);
+        mSharedHelper = SharedHelper.getInstance(ChatActivity.this);
         mDataBaseManager = DataBaseManager.getInstance(ChatActivity.this);
 
         mImagePopupWindow = new ImagePopupWindow(ChatActivity.this, mChatBox);
+        mDensityDpi = ChatActivity.this.getResources().getDisplayMetrics().densityDpi;
     }
 
     private void event() {
-        //文本发送按钮
+        //文本发送按钮点击事件
         mTextSendBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 String text = mContent.getText().toString().trim();
                 if (!text.equals("") && mSmackService != null) {
-                    ygText.setType("txt");
+                    ygText.setType(Contents.STR_MESSAGE_TYPE_TEXT);
                     ygText.setBody(text);
                     new Thread(new Runnable() {
                         @Override
@@ -244,9 +357,11 @@ public class ChatActivity extends AppCompatActivity {
                             try {
                                 ygInfo = mSmackService.sendChatText(mFromJid, ygText.toJson());
                                 if (ygInfo.getCode() == 200) {
-                                    handler.sendEmptyMessage(SEND_TEXT_CHAT);
+                                    //消息发送成功
+                                    handler.sendEmptyMessage(WHAT_SEND_TEXT);
                                 } else {
-                                    handler.sendEmptyMessage(EORROR);
+                                    //消息发送失败
+                                    handler.sendEmptyMessage(WHAT_EORROR);
                                 }
                             } catch (RemoteException e) {
                                 e.printStackTrace();
@@ -261,11 +376,8 @@ public class ChatActivity extends AppCompatActivity {
         mMoreBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                if (mSubMenus.getVisibility() == View.GONE) {
-                    mSubMenus.setVisibility(View.VISIBLE);
-                } else {
-                    mSubMenus.setVisibility(View.GONE);
-                }
+                //子菜单弹出
+                subMenuAnimator(true, true);
             }
         });
 
@@ -276,14 +388,16 @@ public class ChatActivity extends AppCompatActivity {
                 Intent intent1 = new Intent(Intent.ACTION_GET_CONTENT);
                 intent1.addCategory(Intent.CATEGORY_OPENABLE);
                 intent1.setType("image/*");
-                startActivityForResult(Intent.createChooser(intent1, "选择图片"), 1);
+                startActivityForResult(Intent.createChooser(intent1, "选择图片"), INTENT_REQUEST_IMAGE_CAPTURE);
+                subMenuAnimator(false, false);
             }
         });
 
         mContent.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                mSubMenus.setVisibility(View.GONE);
+                //mSubMenus.setVisibility(View.GONE);
+                subMenuAnimator(false, false);
             }
         });
 
@@ -292,7 +406,6 @@ public class ChatActivity extends AppCompatActivity {
             public void onClick(View view) {
                 mRecordWindow.setVisibility(View.GONE);
                 mTextWindow.setVisibility(View.VISIBLE);
-                mSubMenus.setVisibility(View.GONE);
             }
         });
 
@@ -301,16 +414,34 @@ public class ChatActivity extends AppCompatActivity {
             public void onClick(View view) {
                 mRecordWindow.setVisibility(View.VISIBLE);
                 mTextWindow.setVisibility(View.GONE);
-                mSubMenus.setVisibility(View.GONE);
+                subMenuAnimator(true, true);
+            }
+        });
+        mVideoBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+//                CameraPreviewPopupWindow cpw = new CameraPreviewPopupWindow(ChatActivity.this, mChatBox);
+//                cpw.show();
+//                File root = Environment.getExternalStorageDirectory();
+//                File file = new File(root,Config.APP_PATH);
+//                VideoRecorderManager videoRecorderManager = VideoRecorderManager.getInstance(file.getAbsolutePath());
+//                videoRecorderManager.prepareVideo();
+                Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+                //File root = Environment.getExternalStorageDirectory();
+                File file = Utils.getOutputMediaFile(Contents.MEDIA_TYPE_VIDEO);
+                takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Utils.getOutputMediaFileUri(file));
+                if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
+                    startActivityForResult(takeVideoIntent, INTENT_REQUEST_VIDEO_CAPTURE);
+                }
             }
         });
-
         //录音完成监听
         mAudioRecorderButton.setAudioFinishRecorderListener(new AudioRecordeButton.AudioFinishRecorderListener() {
             @Override
             public void onFinish(float seconds, final String filePath) {
                 if (mSmackService != null) {
-                    ygText.setType("audio");
+                    ygText.setType(Contents.STR_MESSAGE_TYPE_AUDIO);
+                    //录音时长
                     ygText.setLength((long) seconds);
                     String str = Utils.file2string(filePath);
                     if (str == null) {
@@ -324,10 +455,12 @@ public class ChatActivity extends AppCompatActivity {
                             try {
                                 ygInfo = mSmackService.sendChatText(mFromJid, ygText.toJson());
                                 if (ygInfo.getCode() == 200) {
+                                    //发送成功
                                     ygText.setBody(filePath);
-                                    handler.sendEmptyMessage(AUDIO_FINISH_RECORDER);
+                                    handler.sendEmptyMessage(WHAT_AUDIO_FINISH_RECORDER);
                                 } else {
-                                    handler.sendEmptyMessage(EORROR);
+                                    //发送失败
+                                    handler.sendEmptyMessage(WHAT_EORROR);
                                 }
                             } catch (RemoteException e) {
                                 e.printStackTrace();
@@ -339,6 +472,37 @@ public class ChatActivity extends AppCompatActivity {
         });
     }
 
+    //底部子菜单向上弹出动画
+    private void subMenuAnimator(boolean isAuto, boolean open) {
+        final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mChatBottomBar.getLayoutParams();
+        ValueAnimator animator;
+        Log.i(TAG, "change:" + lp.height);
+        if (isAuto) {
+            if (lp.height < 70 * (mDensityDpi / 160) + 2) {
+                animator = ValueAnimator.ofInt(70 * (mDensityDpi / 160), 160 * (mDensityDpi / 160));
+            } else {
+                animator = ValueAnimator.ofInt(160 * (mDensityDpi / 160), 70 * (mDensityDpi / 160));
+            }
+        } else {
+            if (open) {
+                animator = ValueAnimator.ofInt(70 * (mDensityDpi / 160), 160 * (mDensityDpi / 160));
+            } else {
+                animator = ValueAnimator.ofInt(70 * (mDensityDpi / 160), 70 * (mDensityDpi / 160));
+            }
+        }
+
+        animator.setDuration(10);
+        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                int x = (int) valueAnimator.getAnimatedValue();
+                lp.height = x;
+                mChatBottomBar.setLayoutParams(lp);
+            }
+        });
+        animator.start();
+    }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.menu_chat, menu);
@@ -364,55 +528,20 @@ public class ChatActivity extends AppCompatActivity {
         return super.onOptionsItemSelected(item);
     }
 
+    //回调
+    @TargetApi(Build.VERSION_CODES.M)
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
         // TODO: 2016/10/31
         if (resultCode == RESULT_OK) {
-            final Uri uri = data.getData();
-            final String filePath = uri.getPath();
-            final String finleName = filePath.substring(filePath.lastIndexOf("/") + 1);
-            Log.i(TAG, uri.getPath());
-            Log.i(TAG, filePath);
-            Log.i(TAG, finleName);
-            if (mSmackService != null) {
-                final YgText ygText = new YgText();
-                ygText.setType("pic");
-                final PutObjectRequest put = new PutObjectRequest(Config.OSS_BUCKET_NAME, finleName, uri.getPath());
-                mOssManger.oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
-                    @Override
-                    public void onSuccess(PutObjectRequest putObjectRequest, PutObjectResult putObjectResult) {
-                        Log.i(TAG, "OSS success");
-                        Log.i(TAG, putObjectRequest.getBucketName());
-                        try {
-                            ygText.setBody(finleName);
-                            ygInfo = mSmackService.sendChatText(mFromJid, ygText.toJson());
-                            if (ygInfo.getCode() == 200) {
-                                YgMessage ygMessage = new YgMessage();
-                                ygMessage.setTo(mToJid);
-                                ygMessage.setFrom(mFromJid);
-                                ygText.setBody(filePath);
-                                ygMessage.setBody(ygText.toJson());
-                                ygMessage.setCustom(1);
-                                mChatAdapter.addChat(new ChatMessageItem(ygMessage));
-                                haveNews = true;
-                            } else {
-                                Log.i(TAG, ygInfo.getBody());
-                            }
-                        } catch (RemoteException e) {
-                            e.printStackTrace();
-                        }
-                    }
-
-                    @Override
-                    public void onFailure(PutObjectRequest putObjectRequest, ClientException e, ServiceException e1) {
-                        Log.i(TAG, "OSS failure");
-                        Log.e("RequestId", e1.getRequestId());
-                        Log.e("ErrorCode", e1.getErrorCode());
-                        Log.e("HostId", e1.getHostId());
-                        Log.e("RawMessage", e1.getRawMessage());
-                    }
-                });
+            switch (requestCode) {
+                case INTENT_REQUEST_IMAGE_CAPTURE:
+                    dealWithImage(data);
+                    break;
+                case INTENT_REQUEST_VIDEO_CAPTURE:
+                    dealWithVideo(data);
+                    break;
             }
         }
     }
@@ -443,7 +572,7 @@ public class ChatActivity extends AppCompatActivity {
             //播放语言
             String filePath = ((TextView) view.findViewById(R.id.filePath)).getText().toString();
             Log.i(TAG, filePath);
-            MediaManager.playSound(filePath, new MediaPlayer.OnCompletionListener() {
+            MediaPlayerManager.getInstance().playAudio(filePath, new MediaPlayer.OnCompletionListener() {
                 @Override
                 public void onCompletion(MediaPlayer mediaPlayer) {
                     if (((String) mAnimView.getTag()).equals("left")) {
@@ -451,7 +580,6 @@ public class ChatActivity extends AppCompatActivity {
                     } else {
                         mAnimView.setBackgroundResource(R.mipmap.adj);
                     }
-
                 }
             });
         }
@@ -468,16 +596,49 @@ public class ChatActivity extends AppCompatActivity {
         }
     }
 
+    private class OnVideoClickListener implements View.OnClickListener {
+
+        @Override
+        public void onClick(View view) {
+            //String path = (String) view.getTag();
+            ChatSurfaceView chatSurfaceView = (ChatSurfaceView) view;
+            String path = (String) chatSurfaceView.getTag();
+            MediaPlayerManager.getInstance().playVideo(chatSurfaceView, path, chatSurfaceView.getOnCompletionListener());
+        }
+    }
+
+    private class OnVideoDoubleClickListener implements ChatSurfaceView.OnVideoDoubleClickListener {
+
+        @Override
+        public void onDoubleClick(View view) {
+            ChatSurfaceView chatSurfaceView = (ChatSurfaceView) view;
+            String path = (String) chatSurfaceView.getTag();
+
+            Intent intent = new Intent(ChatActivity.this, VideoPreviewWindowActivity.class);
+            intent.putExtra(Contents.KEY_VIDEO_PATH, path);
+            startActivity(intent);
+        }
+    }
+
     private class MsgRecervier extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             YgMessage ygMessage = intent.getParcelableExtra("msg");
             Log.i(TAG, "received message");
             if (ygMessage.getFrom().split("@")[0].equals(mFromJid.split("@")[0])) {
-                ChatMessageItem item = new ChatMessageItem(ygMessage);
-                if (item.getType() == Config.INT_TYPE_PIC_L){
-                    ossLoadImage(item);
-                }else {
+                Log.i(TAG, "c:" + ygMessage.getCustom());
+                final ChatMessageItem item = new ChatMessageItem(ygMessage);
+                if (item.getType() == Contents.CHAT_TYPE_IMAGE_L_INT) {
+                    Message msg = new Message();
+                    msg.what = WHAT_DOWNLOAD_IMAGE;
+                    msg.obj = item;
+                    handler.handleMessage(msg);
+                } else if (item.getType() == Contents.CHAT_TYPE_VIDEO_L_INT) {
+                    Message msg = new Message();
+                    msg.what = WHAT_DOWNLOAD_VIDEO;
+                    msg.obj = item;
+                    handler.handleMessage(msg);
+                } else {
                     mChatAdapter.addChat(item);
                     mChatBox.setSelection(mChatAdapter.getCount() - 1);
                     haveNews = true;
@@ -486,34 +647,55 @@ public class ChatActivity extends AppCompatActivity {
             }
         }
     }
-    private void ossLoadImage(final ChatMessageItem item){
+
+    /**
+     * 加载阿里云 对象存储图片到本地
+     *
+     * @param item
+     */
+    private void OSSDownloadImage(final ChatMessageItem item) {
         final String fileName = item.getText();
-        Log.i(TAG,"recerve filename :"+fileName);
-        GetObjectRequest get = new GetObjectRequest(Config.OSS_BUCKET_NAME,fileName);
+        Log.i(TAG, "recerve filename :" + fileName);
+        //设置图片消息状态为 正在接收
+        //item.setSendStatus(Config.CHAT_MESSAGE_SEND_STATUS_SENDING);
+        //消息在本地sqlite 中的id
+        //final long id = mChatAdapter.addChat(item);
+        //当前消息位置
+        //final int position = mChatAdapter.getCount() - 1;
+        //haveNews = true;
+        GetObjectRequest get = new GetObjectRequest(Config.OSS_BUCKET_NAME, fileName);
         mOssManger.oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
             @Override
             public void onSuccess(GetObjectRequest getObjectRequest, GetObjectResult getObjectResult) {
+                //阿里云 对象存储 请求成功 开始接收文件
                 InputStream inputStream = getObjectResult.getObjectContent();
-                File picPath = new File(new File(Environment.getExternalStorageDirectory(), Config.APP_PATH),Config.PIC_PATH);
+                File picPath = new File(new File(Environment.getExternalStorageDirectory(), Config.APP_PATH), Config.PIC_PATH);
                 if (!picPath.exists()) picPath.mkdirs();
-                String ext = fileName.substring(fileName.lastIndexOf(".")+1);
-                File file = new File(picPath,System.currentTimeMillis()+ext);
+                String ext = fileName.substring(fileName.lastIndexOf("."));
+                File file = new File(picPath, System.currentTimeMillis() + ext);
                 try {
                     OutputStream outputStream = new FileOutputStream(file);
-                    byte[] buffer= new byte[1024];
+                    byte[] buffer = new byte[1024];
                     int len;
-                    while ((len=inputStream.read(buffer))!=-1){
-                        outputStream.write(buffer,0,len);
+                    while ((len = inputStream.read(buffer)) != -1) {
+                        outputStream.write(buffer, 0, len);
                     }
                     inputStream.close();
                     outputStream.flush();
                     outputStream.close();
-
+                    //文件接收完成 改变消息状态为 接收完成
+                    item.setSendStatus(Contents.MESSAGE_STATUS_SENT);
                     item.setText(file.getAbsolutePath());
-
-                    mChatAdapter.addChat(item);
-                    mChatBox.setSelection(mChatAdapter.getCount() - 1);
-                    haveNews = true;
+                    //mDataBaseManager.updateChatMessageItem(id, item);
+                    //更新消息显示视图
+                    Message msg = new Message();
+                    msg.what = WHAT_SHOW_IMAGE;
+                    msg.obj = item;
+                    Bundle bundle = new Bundle();
+                    bundle.putInt(KEY_CHAT_POSITION, 1);
+                    bundle.putString(KEY_CHAT_IMAGE_PATH, file.getAbsolutePath());
+                    msg.setData(bundle);
+                    handler.handleMessage(msg);
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                 } catch (IOException e) {
@@ -539,6 +721,169 @@ public class ChatActivity extends AppCompatActivity {
             }
         });
     }
+
+    private void OSSDownloadVideo(final ChatMessageItem item) {
+        // TODO: 2016/11/30
+        final String fileName = item.getText();
+        GetObjectRequest get = new GetObjectRequest(Config.OSS_BUCKET_NAME, fileName);
+        mOssManger.oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
+            @Override
+            public void onSuccess(GetObjectRequest getObjectRequest, GetObjectResult getObjectResult) {
+                InputStream inputStream = getObjectResult.getObjectContent();
+                File picPath = new File(new File(Environment.getExternalStorageDirectory(), Config.APP_PATH), Config.PIC_PATH);
+                if (!picPath.exists()) picPath.mkdirs();
+                File file = new File(picPath, fileName);
+                try {
+                    OutputStream outputStream = new FileOutputStream(file);
+                    byte[] buffer = new byte[1024];
+                    int len;
+                    while ((len = inputStream.read(buffer)) != -1) {
+                        outputStream.write(buffer, 0, len);
+                    }
+                    outputStream.flush();
+                    outputStream.close();
+                    inputStream.close();
+
+                    item.setSendStatus(Contents.MESSAGE_STATUS_SENT);
+                    item.setText(file.getAbsolutePath());
+
+                    Message msg = new Message();
+                    msg.what = WHAT_SHOW_VIDEO;
+                    msg.obj = item;
+                    handler.handleMessage(msg);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+
+            @Override
+            public void onFailure(GetObjectRequest getObjectRequest, ClientException e, ServiceException e1) {
+
+            }
+        });
+    }
+
+    private void dealWithImage(Intent data) {
+        Uri uri = data.getData();
+        final String filePath = uri.getPath();
+        final String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
+        Log.i(TAG, uri.getPath());
+        Log.i(TAG, filePath);
+        Log.i(TAG, fileName);
+        final YgText ygText = new YgText();
+        ygText.setType(Contents.STR_MESSAGE_TYPE_IMAGE);
+        ygText.setBody(filePath);
+
+        YgMessage message = new YgMessage();
+        message.setTo(mToJid);
+        message.setFrom(mFromJid);
+        message.setCustom(1);
+        message.setBody(ygText.toJson());
+
+        final ChatMessageItem chatMessageItem = new ChatMessageItem(message);
+        chatMessageItem.setSendStatus(Contents.MESSAGE_STATUS_SENDING);
+        final long id = mChatAdapter.addChat(chatMessageItem);
+        final int position = mChatAdapter.getCount() - 1;
+        if (mSmackService != null) {
+            final PutObjectRequest put = new PutObjectRequest(Config.OSS_BUCKET_NAME, fileName, uri.getPath());
+            mOssManger.oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
+                @Override
+                public void onSuccess(PutObjectRequest putObjectRequest, PutObjectResult putObjectResult) {
+                    Log.i(TAG, "OSS success");
+                    Log.i(TAG, putObjectRequest.getBucketName());
+                    try {
+                        ygText.setBody(fileName);
+                        ygInfo = mSmackService.sendChatText(mFromJid, ygText.toJson());
+                        if (ygInfo.getCode() == 200) {
+                            Log.i(TAG, "Send Pic success");
+                            chatMessageItem.setSendStatus(Contents.MESSAGE_STATUS_SENT);
+                            mDataBaseManager.updateChatMessageItem(id, chatMessageItem);
+                            Message msg = new Message();
+                            msg.what = WHAT_SEND_IMAGE;
+                            msg.arg1 = position;
+                            handler.handleMessage(msg);
+                            Log.i(TAG, "send process");
+                        } else {
+                            Log.i(TAG, ygInfo.getBody());
+                        }
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                @Override
+                public void onFailure(PutObjectRequest putObjectRequest, ClientException e, ServiceException e1) {
+                    Log.i(TAG, "OSS failure");
+                    Log.e("RequestId", e1.getRequestId());
+                    Log.e("ErrorCode", e1.getErrorCode());
+                    Log.e("HostId", e1.getHostId());
+                    Log.e("RawMessage", e1.getRawMessage());
+                }
+            });
+        }
+        Log.i(TAG, "chiren count:" + mChatBox.getChildCount());
+    }
+
+    private void dealWithVideo(Intent data) {
+        Uri uri = data.getData();
+        String filePath = uri.getPath();
+        final String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
+        Log.i(TAG, filePath);
+        Log.i(TAG, fileName);
+        Log.i(TAG, "Video:" + uri.getPath());
+
+        final YgText ygText = new YgText();
+        ygText.setType(Contents.STR_MESSAGE_TYPE_VIDEO);
+        ygText.setBody(filePath);
+
+        YgMessage message = new YgMessage();
+        message.setTo(mToJid);
+        message.setFrom(mFromJid);
+        message.setCustom(1);
+        message.setBody(ygText.toJson());
+
+        final ChatMessageItem chatMessageItem = new ChatMessageItem(message);
+        chatMessageItem.setSendStatus(Contents.MESSAGE_STATUS_SENDING);
+
+        final long id = mChatAdapter.addChat(chatMessageItem);
+        final int position = mChatAdapter.getCount() - 1;
+
+        if (mSmackService != null) {
+            PutObjectRequest put = new PutObjectRequest(Config.OSS_BUCKET_NAME, fileName, filePath);
+            mOssManger.oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
+                @Override
+                public void onSuccess(PutObjectRequest putObjectRequest, PutObjectResult putObjectResult) {
+                    ygText.setBody(fileName);
+                    try {
+                        ygInfo = mSmackService.sendChatText(mFromJid, ygText.toJson());
+                        if (ygInfo.getCode() == 200) {
+                            chatMessageItem.setSendStatus(Contents.MESSAGE_STATUS_SENT);
+                            mDataBaseManager.updateChatMessageItem(id, chatMessageItem);
+                            Message msg = new Message();
+                            msg.what = WHAT_SEND_VIDEO;
+                            msg.arg1 = position;
+                            handler.handleMessage(msg);
+                        }
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                @Override
+                public void onFailure(PutObjectRequest putObjectRequest, ClientException e, ServiceException e1) {
+                    Log.i(TAG, "OSS failure");
+                    Log.e("RequestId", e1.getRequestId());
+                    Log.e("ErrorCode", e1.getErrorCode());
+                    Log.e("HostId", e1.getHostId());
+                    Log.e("RawMessage", e1.getRawMessage());
+                }
+            });
+        }
+
+    }
+
     private class ServiceConn implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
@@ -573,18 +918,19 @@ public class ChatActivity extends AppCompatActivity {
 
     @Override
     protected void onPause() {
+        //更新聊天主窗口
         if (haveNews) {
             mChatAdapter.finish();
             haveNews = false;
         }
-        MediaManager.pause();
+        MediaPlayerManager.getInstance().pause();
         super.onPause();
     }
 
     @Override
     protected void onResume() {
         super.onResume();
-        MediaManager.resume();
+        MediaPlayerManager.getInstance().resume();
     }
 
     @Override
@@ -596,7 +942,7 @@ public class ChatActivity extends AppCompatActivity {
     protected void onDestroy() {
         unbindService(mConn);
         unregisterReceiver(mMsgRecervier);
-        MediaManager.release();
+        MediaPlayerManager.getInstance().release();
         super.onDestroy();
     }
 }
index 4a4c699..5ff3c96 100644 (file)
@@ -38,28 +38,36 @@ import cc.minsnail.view.ImagePopupWindow;
 public class MainActivity extends AppCompatActivity {
     private static final int SHOW_INFO = 1;
     private static final String TAG = "MainActivity";
+    //用户名
     private String mToUserName;
     private IServiceAidlInterface mSmackService;
     private ServiceConn mConn;
+    //联系人列表
     private RosterFragment mRosterFragment;
+    //主页
     private MessageFragment mMessageFragment;
+    //主页消息消息显示listView
     private TextView mMessage;
+    //联系人显示ListView
     private TextView mRoster;
+    //tool bar
     private Toolbar mToolbar;
     private TextView mToolbarTitle;
     private SharedHelper mSharedHelper;
+    //
     private ImagePopupWindow popupWindow;
-    private Handler handler = new Handler(){
+    private Handler handler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            switch (msg.what){
+            switch (msg.what) {
                 case SHOW_INFO:
                     mToolbar.setTitle(mToUserName);
-                    mSharedHelper.put("toUserName",mToUserName);
+                    mSharedHelper.put("toUserName", mToUserName);
                     break;
             }
         }
     };
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -70,27 +78,31 @@ public class MainActivity extends AppCompatActivity {
         setSupportActionBar(mToolbar);
         initView();
         initEvent();
+
         mConn = new ServiceConn();
         Intent intent = new Intent("android.intent.action.SMACK_CLIENT_SERVICE");
         intent.setPackage("cc.minsnail.www.smackclient");
-        bindService(intent,mConn, Context.BIND_AUTO_CREATE);
+        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
 
-        mSharedHelper = new SharedHelper(MainActivity.this);
-        popupWindow = new ImagePopupWindow(MainActivity.this,mMessage);
+        mSharedHelper = SharedHelper.getInstance(MainActivity.this);
+        popupWindow = new ImagePopupWindow(MainActivity.this, mMessage);
     }
-    private void initView(){
+
+    private void initView() {
         mToolbarTitle = (TextView) mToolbar.findViewById(R.id.toolbar_title);
-        mMessage = (TextView)findViewById(R.id.message);
+        mMessage = (TextView) findViewById(R.id.message);
         mRoster = (TextView) findViewById(R.id.roster);
     }
-    private void initEvent(){
+
+    private void initEvent() {
         mMessage.setOnClickListener(listener);
         mRoster.setOnClickListener(listener);
     }
+
     private View.OnClickListener listener = new View.OnClickListener() {
         @Override
         public void onClick(View view) {
-            switch (view.getId()){
+            switch (view.getId()) {
                 case R.id.message:
                     mToolbarTitle.setText("消息");
                     showFragment(0);
@@ -102,24 +114,25 @@ public class MainActivity extends AppCompatActivity {
             }
         }
     };
-    private void showFragment(int item){
+
+    private void showFragment(int item) {
         FragmentManager fragmentManager = getFragmentManager();
         FragmentTransaction transaction = fragmentManager.beginTransaction();
         hideAllFragment(transaction);
-        switch (item){
+        switch (item) {
             case 0:
-                if (mMessageFragment == null){
+                if (mMessageFragment == null) {
                     mMessageFragment = new MessageFragment();
-                    transaction.add(R.id.main_fragment,mMessageFragment);
-                }else {
+                    transaction.add(R.id.main_fragment, mMessageFragment);
+                } else {
                     transaction.show(mMessageFragment);
                 }
                 break;
             case 1:
-                if (mRosterFragment==null){
+                if (mRosterFragment == null) {
                     mRosterFragment = new RosterFragment(mSmackService);
-                    transaction.add(R.id.main_fragment,mRosterFragment);
-                }else {
+                    transaction.add(R.id.main_fragment, mRosterFragment);
+                } else {
                     transaction.show(mRosterFragment);
                 }
                 break;
@@ -128,18 +141,22 @@ public class MainActivity extends AppCompatActivity {
         }
         transaction.commit();
     }
-    private void hideAllFragment(FragmentTransaction transaction){
-        if (mRosterFragment!=null) transaction.hide(mRosterFragment);
-        if (mMessageFragment!=null) transaction.hide(mMessageFragment);
+
+    private void hideAllFragment(FragmentTransaction transaction) {
+        if (mRosterFragment != null) transaction.hide(mRosterFragment);
+        if (mMessageFragment != null) transaction.hide(mMessageFragment);
     }
-    private void init(){
+
+    private void init() {
         showInfo();
     }
-    private void showInfo(){
+
+    //显示个人信息
+    private void showInfo() {
         new Thread(new Runnable() {
             @Override
             public void run() {
-                if (mSmackService != null){
+                if (mSmackService != null) {
                     try {
                         mToUserName = mSmackService.getAccountAttribute("username");
                         handler.sendEmptyMessage(SHOW_INFO);
@@ -150,17 +167,18 @@ public class MainActivity extends AppCompatActivity {
             }
         }).start();
     }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.menu_main,menu);
+        getMenuInflater().inflate(R.menu.menu_main, menu);
         return super.onCreateOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()){
+        switch (item.getItemId()) {
             case R.id.add_frd:
-                Intent intent = new Intent(getApplicationContext(),SearchUserActivity.class);
+                Intent intent = new Intent(getApplicationContext(), SearchUserActivity.class);
                 startActivity(intent);
                 break;
             case R.id.add_grp:
@@ -173,7 +191,8 @@ public class MainActivity extends AppCompatActivity {
         }
         return super.onOptionsItemSelected(item);
     }
-    private void loginOut(){
+
+    private void loginOut() {
         AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
         builder.setTitle(R.string.str_login_out_dialog_title)
                 .setMessage(R.string.str_login_out_dialog_message);
@@ -194,10 +213,11 @@ public class MainActivity extends AppCompatActivity {
         AlertDialog dialog = builder.create();
         dialog.show();
     }
+
     class ServiceConn implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
-            Log.d(TAG,"连接服务器成功");
+            Log.d(TAG, "连接服务器成功");
             mSmackService = IServiceAidlInterface.Stub.asInterface(iBinder);
 
             init();
@@ -206,17 +226,19 @@ public class MainActivity extends AppCompatActivity {
 
         @Override
         public void onServiceDisconnected(ComponentName componentName) {
-            Log.d(TAG,"连接服务失败");
+            Log.d(TAG, "连接服务失败");
             mSmackService = null;
         }
     }
+
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK){
-            Log.i(TAG,"finish");
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            Log.i(TAG, "finish");
             this.finish();
         }
         return false;
     }
+
     @Override
     protected void onDestroy() {
         unbindService(mConn);
index cd9d224..f18bd46 100644 (file)
@@ -44,40 +44,40 @@ public class RegisterActivity extends AppCompatActivity {
     private ServiceConn mConn;
     private IServiceAidlInterface mSmackService;
     private DatePickerDialog mDatePickerDialog;
-    private int mUsex=1;
+    private int mUsex = 1;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_register);
-        init();
         initView();
         initEvent();
+
         //绑定服务后台服务
         mConn = new ServiceConn();
         startService(new Intent(getApplicationContext(), SmackService.class));
         Intent intent = new Intent("android.intent.action.SMACK_CLIENT_SERVICE");
         intent.setPackage("cc.minsnail.www.smackclient");
-        bindService(intent,mConn, Context.BIND_AUTO_CREATE);
+        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
 
     }
-    private void init(){
-        mUser = (EditText)findViewById(R.id.user);
-        mPass = (EditText)findViewById(R.id.pass);
-        mEmail = (EditText)findViewById(R.id.email);
-        mName = (EditText)findViewById(R.id.firstname);
+
+    private void initView() {
+        mUser = (EditText) findViewById(R.id.user);
+        mPass = (EditText) findViewById(R.id.pass);
+        mEmail = (EditText) findViewById(R.id.email);
+        mName = (EditText) findViewById(R.id.firstname);
         mBirthDay = (EditText) findViewById(R.id.birth);
         mBirthDay.setInputType(InputType.TYPE_NULL);
         mSex = (RadioGroup) findViewById(R.id.sex);
         mPhone = (EditText) findViewById(R.id.phone);
 
-        mRegisterBtn = (Button)findViewById(R.id.button);
-    }
-    private void initView(){
+        mRegisterBtn = (Button) findViewById(R.id.button);
         //性别选择
         mSex.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(RadioGroup radioGroup, int i) {
-                switch (i){
+                switch (i) {
                     case R.id.male:
                         mUsex = 1;
                         break;
@@ -95,9 +95,9 @@ public class RegisterActivity extends AppCompatActivity {
         mDatePickerDialog = new DatePickerDialog(RegisterActivity.this, new DatePickerDialog.OnDateSetListener() {
             @Override
             public void onDateSet(DatePicker datePicker, int year, int moth, int day) {
-                mBirthDay.setText(year+"/"+moth+"/"+day);
+                mBirthDay.setText(year + "/" + moth + "/" + day);
             }
-        },calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),Calendar.DAY_OF_MONTH);
+        }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), Calendar.DAY_OF_MONTH);
         mBirthDay.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View view, MotionEvent motionEvent) {
@@ -108,16 +108,17 @@ public class RegisterActivity extends AppCompatActivity {
 
 
     }
-    private void initEvent(){
+
+    private void initEvent() {
         //登录按钮
         mRegisterBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                if (mUser.getText().toString().trim().equals("")||mPass.getText().toString().trim().equals("")){
-                    Toast.makeText(getApplicationContext(),"user or password not null",Toast.LENGTH_SHORT).show();
+                if (mUser.getText().toString().trim().equals("") || mPass.getText().toString().trim().equals("")) {
+                    Toast.makeText(getApplicationContext(), "user or password not null", Toast.LENGTH_SHORT).show();
                     return;
                 }
-                if (mSmackService != null){
+                if (mSmackService != null) {
                     YgUserConfig config = new YgUserConfig();
                     config.setBirth(mBirthDay.getText().toString());
                     config.setName(mName.getText().toString());
@@ -125,42 +126,45 @@ public class RegisterActivity extends AppCompatActivity {
                     config.setSex(mUsex);
                     config.setMobile(mPhone.getText().toString());
                     try {
-                        YgInfo ygInfo = mSmackService.registUser(mUser.getText().toString(),mPass.getText().toString(),config);
-                        if (ygInfo.getCode()==200){
-                            Toast.makeText(getApplicationContext(),ygInfo.getBody(),Toast.LENGTH_SHORT).show();
-                            startActivity(new Intent(getApplicationContext(),LoginActivity.class).putExtra("user",mUser.getText().toString()));
-                        }else {
-                            Toast.makeText(getApplicationContext(),ygInfo.getBody(),Toast.LENGTH_SHORT).show();
+                        YgInfo ygInfo = mSmackService.registUser(mUser.getText().toString(), mPass.getText().toString(), config);
+                        if (ygInfo.getCode() == 200) {
+                            Toast.makeText(getApplicationContext(), ygInfo.getBody(), Toast.LENGTH_SHORT).show();
+                            startActivity(new Intent(getApplicationContext(), LoginActivity.class).putExtra("user", mUser.getText().toString()));
+                        } else {
+                            Toast.makeText(getApplicationContext(), ygInfo.getBody(), Toast.LENGTH_SHORT).show();
                         }
                     } catch (RemoteException e) {
                         e.printStackTrace();
                     }
-                }else {
-                    Toast.makeText(getApplicationContext(),"未连接到服务器",Toast.LENGTH_SHORT).show();
+                } else {
+                    Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show();
                 }
             }
         });
     }
+
     class ServiceConn implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
-            Log.d(TAG,"连接服务器成功");
+            Log.d(TAG, "连接服务器成功");
             mSmackService = IServiceAidlInterface.Stub.asInterface(iBinder);
         }
 
         @Override
         public void onServiceDisconnected(ComponentName componentName) {
-            Log.d(TAG,"连接服务失败");
+            Log.d(TAG, "连接服务失败");
             mSmackService = null;
         }
     }
+
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK){
-            Log.i(TAG,"finish");
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            Log.i(TAG, "finish");
             this.finish();
         }
         return false;
     }
+
     @Override
     protected void onDestroy() {
         unbindService(mConn);
index c2b378d..e9bf779 100644 (file)
@@ -42,6 +42,7 @@ public class SearchUserActivity extends AppCompatActivity {
     private ListView mUsers;
     private ImageButton mSearchBtn;
     private Toolbar mToolbar;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
index 847fd0f..cf1b84c 100644 (file)
@@ -12,15 +12,17 @@ import cc.minsnail.smackclient.R;
  */
 public class UserDetailsActivity extends AppCompatActivity {
     private static final String TAG = "UserDetailsActivity";
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_user_details);
         setTitle("用户详情");
     }
+
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK){
-            Log.i(TAG,"finish");
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            Log.i(TAG, "finish");
             this.finish();
         }
         return false;
index 2efe324..12199d4 100644 (file)
@@ -32,11 +32,12 @@ public class UserInfoActivity extends AppCompatActivity {
     private Button mAddBtn;
     private IServiceAidlInterface mSmackService;
     private ServiceConn mConn;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_userinfo);
-        init();
+        initView();
 
         Intent i = getIntent();
         mJid = i.getStringExtra("jid");
@@ -48,29 +49,31 @@ public class UserInfoActivity extends AppCompatActivity {
         mConn = new ServiceConn();
         Intent intent = new Intent("android.intent.action.SMACK_CLIENT_SERVICE");
         intent.setPackage("cc.minsnail.www.smackclient");
-        bindService(intent,mConn, Context.BIND_AUTO_CREATE);
+        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
     }
-    private void init(){
-        mUser = (TextView)findViewById(R.id.user);
-        mBeizhu = (EditText)findViewById(R.id.beizhu);
-        mAddBtn = (Button)findViewById(R.id.add);
+
+    private void initView() {
+        mUser = (TextView) findViewById(R.id.user);
+        mBeizhu = (EditText) findViewById(R.id.beizhu);
+        mAddBtn = (Button) findViewById(R.id.add);
     }
-    private void initEvent(){
+
+    private void initEvent() {
         mAddBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                Log.i(TAG,"add user");
+                Log.i(TAG, "add user");
                 YgInfo info = null;
                 try {
-                    info = mSmackService.addFriend(mJid,mBeizhu.getText().toString(),new String[]{"hdu"});
-                    if (info!=null&&info.getCode()==200){
-                        Toast.makeText(getApplicationContext(),info.getBody(),Toast.LENGTH_SHORT).show();
-                        startActivity(new Intent(getApplicationContext(),MainActivity.class));
+                    info = mSmackService.addFriend(mJid, mBeizhu.getText().toString(), new String[]{"hdu"});
+                    if (info != null && info.getCode() == 200) {
+                        Toast.makeText(getApplicationContext(), info.getBody(), Toast.LENGTH_SHORT).show();
+                        startActivity(new Intent(getApplicationContext(), MainActivity.class));
                     }
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
-                Log.d(TAG,info.getBody());
+                Log.d(TAG, info.getBody());
             }
         });
     }
@@ -78,12 +81,12 @@ public class UserInfoActivity extends AppCompatActivity {
     private class ServiceConn implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
-            Log.d(TAG,"连接服务器成功");
+            Log.d(TAG, "连接服务器成功");
             mSmackService = IServiceAidlInterface.Stub.asInterface(iBinder);
-            if (mSmackService !=null){
+            if (mSmackService != null) {
                 try {
                     YgVCard ygVCard = mSmackService.getOneVCard(mJid);
-                    Log.i(TAG,ygVCard.toJson());
+                    Log.i(TAG, ygVCard.toJson());
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
@@ -92,17 +95,19 @@ public class UserInfoActivity extends AppCompatActivity {
 
         @Override
         public void onServiceDisconnected(ComponentName componentName) {
-            Log.d(TAG,"连接服务失败");
+            Log.d(TAG, "连接服务失败");
             mSmackService = null;
         }
     }
+
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK){
-            Log.i(TAG,"finish");
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            Log.i(TAG, "finish");
             this.finish();
         }
         return false;
     }
+
     @Override
     protected void onDestroy() {
         unbindService(mConn);
index f159ee4..94ead9d 100644 (file)
@@ -1,27 +1,36 @@
 package cc.minsnail.adapter;
 
 import android.annotation.TargetApi;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.LruCache;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
+import android.widget.ImageButton;
 import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import cc.minsnail.Contents;
 import cc.minsnail.beans.ChatMessageItem;
-import cc.minsnail.config.Config;
 import cc.minsnail.database.DataBaseManager;
 import cc.minsnail.smackclient.R;
 import cc.minsnail.view.ChatImageView;
+import cc.minsnail.view.ChatSurfaceView;
 
 /**
  * Created by yg on 2016/9/23.
@@ -29,17 +38,31 @@ import cc.minsnail.view.ChatImageView;
 public class ChatAdapter extends BaseAdapter {
     private static final String TAG = "ChatAdapter";
     private Context mContext;
+    private ListView mChatBox;
+    //数据集
     private List<ChatMessageItem> mDatas;
+    //视图集
+    private Map<Integer, View> mViews;
     private LayoutInflater mInflater;
     private int mMinItemWidth;
     private int mMaxItemWidth;
+    //sqlite操作对象
     private DataBaseManager mDataBaseManager;
+    //音频消息点击事件(播放音频)
     private View.OnClickListener mOnAudioClickListener;
+    //图片消息点击事件(放大图片)
     private View.OnClickListener mOnImageClickListener;
+    private View.OnClickListener mOnVideoClickListener;
+    private ChatSurfaceView.OnVideoDoubleClickListener mOnVideoDoubleClickListener;
+    //图片内存缓存对象
+    private LruCache<String, Bitmap> mPicLruCache;
+    private LruCache<String, Drawable> mVideoThumbnailCache;
+    private ContentResolver mResolver;
 
-    public ChatAdapter(Context context, List<ChatMessageItem> list, View.OnClickListener onAudioClickListener,View.OnClickListener onImageClickListener) {
-        this.mContext = context;
-        this.mDatas = list;
+    public ChatAdapter(Context context, List<ChatMessageItem> list, ListView listView) {
+        mContext = context;
+        mChatBox = listView;
+        mDatas = list;
         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         DisplayMetrics outMetrics = new DisplayMetrics();
         wm.getDefaultDisplay().getMetrics(outMetrics);
@@ -47,14 +70,40 @@ public class ChatAdapter extends BaseAdapter {
         mMinItemWidth = (int) (outMetrics.widthPixels * 0.15f);
         mInflater = LayoutInflater.from(mContext);
         mDataBaseManager = DataBaseManager.getInstance(mContext);
-        mOnAudioClickListener = onAudioClickListener;
+        mPicLruCache = new LruCache<String, Bitmap>((int) ((Runtime.getRuntime().maxMemory() / 1024) / 8)) {
+            @Override
+            protected int sizeOf(String key, Bitmap value) {
+                return value.getByteCount() / 1024;
+            }
+        };
+        mVideoThumbnailCache = new LruCache<String, Drawable>((int) ((Runtime.getRuntime().maxMemory()) / 1024) / 8);
+        mViews = new HashMap<>();
+
+        mResolver = mContext.getContentResolver();
+    }
+
+    public void setOnAudioClickListener(View.OnClickListener listener) {
+        mOnAudioClickListener = listener;
+    }
+
+    public void setOnImageClickListener(View.OnClickListener onImageClickListener) {
         mOnImageClickListener = onImageClickListener;
     }
 
-    public void addChat(ChatMessageItem item) {
-        mDataBaseManager.insertChatMessageItem(item);
-        this.mDatas.add(item);
+    public void setOnVideoClickListener(View.OnClickListener onVideoClickListener) {
+        mOnVideoClickListener = onVideoClickListener;
+    }
+
+    public void setOnVideoDoubleClickListener(ChatSurfaceView.OnVideoDoubleClickListener onVideoDoubleClickListener) {
+        mOnVideoDoubleClickListener = onVideoDoubleClickListener;
+    }
+
+    //添加消息到聊天窗口并保存到sqlite
+    public long addChat(final ChatMessageItem item) {
+        long index = mDataBaseManager.insertChatMessageItem(item);
+        mDatas.add(item);
         notifyDataSetChanged();
+        return index;
     }
 
     @Override
@@ -79,7 +128,20 @@ public class ChatAdapter extends BaseAdapter {
 
     @Override
     public int getViewTypeCount() {
-        return 6;
+        return 8;
+    }
+
+    /**
+     * 返回消息item 视图View
+     *
+     * @param position 位置
+     * @return
+     */
+    public View getView(int position) {
+        if (mViews.containsKey(position)) {
+            return mViews.get(position);
+        }
+        return null;
     }
 
     @TargetApi(Build.VERSION_CODES.M)
@@ -91,39 +153,53 @@ public class ChatAdapter extends BaseAdapter {
         PicHolderR picHolderR = null;
         AudioHolderL audioHolderL = null;
         AudioHolderR audioHolderR = null;
+        VideoHodlerR videoHodlerR = null;
+        VideoHodlerL videoHodlerL = null;
         int type = getItemViewType(i);
+        Log.i(TAG, "type:" + type);
         ChatMessageItem item = mDatas.get(i);
         if (view == null) {
             switch (type) {
-                case Config.INT_TYPE_TXT_L:
+                //收到文本类型消息 显示在窗口左边视图
+                case Contents.CHAT_TYPE_TEXT_L_INT:
                     view = mInflater.inflate(R.layout.chat_txt_item_1, viewGroup, false);
                     txtHolderL = new TxtHolderL();
                     txtHolderL.head = (ImageView) view.findViewById(R.id.head);
                     txtHolderL.text = (TextView) view.findViewById(R.id.text);
                     view.setTag(txtHolderL);
                     break;
-                case Config.INT_TYPE_TXT_R:
+
+                //发出的文本详细 显示在窗口右边视图
+                case Contents.CHAT_TYPE_TEXT_R_INT:
                     view = mInflater.inflate(R.layout.chat_txt_item_2, viewGroup, false);
                     txtHolderR = new TxtHolderR();
                     txtHolderR.head = (ImageView) view.findViewById(R.id.head);
                     txtHolderR.text = (TextView) view.findViewById(R.id.text);
                     view.setTag(txtHolderR);
                     break;
-                case Config.INT_TYPE_PIC_L:
+
+                //收到的图片类型消息 显示在窗口左边视图
+                case Contents.CHAT_TYPE_IMAGE_L_INT:
                     view = mInflater.inflate(R.layout.chat_pic_item_1, viewGroup, false);
                     picHolderL = new PicHolderL();
                     picHolderL.head = (ImageView) view.findViewById(R.id.head);
                     picHolderL.pic = (ChatImageView) view.findViewById(R.id.pic);
+                    picHolderL.progressBar = (ProgressBar) view.findViewById(R.id.image_progress_bar);
                     view.setTag(picHolderL);
                     break;
-                case Config.INT_TYPE_PIC_R:
+
+                //发出的图片类型消息 显示在窗口右边
+                case Contents.CHAT_TYPE_IMAGE_R_INT:
                     view = mInflater.inflate(R.layout.chat_pic_item_2, viewGroup, false);
                     picHolderR = new PicHolderR();
                     picHolderR.head = (ImageView) view.findViewById(R.id.head);
                     picHolderR.pic = (ChatImageView) view.findViewById(R.id.pic);
+                    picHolderR.progressBar = (ProgressBar) view.findViewById(R.id.image_progress_bar);
                     view.setTag(picHolderR);
                     break;
-                case Config.INT_TYPE_AUDIO_L:
+
+                //收到的音频类型的详细 显示在窗口左边视图
+                case Contents.CHAT_TYPE_AUDIO_L_INT:
                     view = mInflater.inflate(R.layout.chat_audio_item_1, viewGroup, false);
                     audioHolderL = new AudioHolderL();
                     audioHolderL.head = (ImageView) view.findViewById(R.id.head);
@@ -132,7 +208,9 @@ public class ChatAdapter extends BaseAdapter {
                     audioHolderL.recorder_len = (FrameLayout) view.findViewById(R.id.recoder_len);
                     view.setTag(audioHolderL);
                     break;
-                case Config.INT_TYPE_AUDIO_R:
+
+                //发出的音频消息 显示在窗口的右边
+                case Contents.CHAT_TYPE_AUDIO_R_INT:
                     view = mInflater.inflate(R.layout.chat_audio_item_2, viewGroup, false);
                     audioHolderR = new AudioHolderR();
                     audioHolderR.head = (ImageView) view.findViewById(R.id.head);
@@ -141,80 +219,155 @@ public class ChatAdapter extends BaseAdapter {
                     audioHolderR.recorder_len = (FrameLayout) view.findViewById(R.id.recoder_len);
                     view.setTag(audioHolderR);
                     break;
+
+                case Contents.CHAT_TYPE_VIDEO_R_INT:
+                    view = mInflater.inflate(R.layout.chat_vid_item_2, viewGroup, false);
+                    videoHodlerR = new VideoHodlerR();
+                    videoHodlerR.videoView = (ChatSurfaceView) view.findViewById(R.id.chat_video);
+                    videoHodlerR.videoMask = (ImageView) view.findViewById(R.id.video_mask);
+                    videoHodlerR.playBtn = (ImageButton) view.findViewById(R.id.video_mask_play);
+                    view.setTag(videoHodlerR);
+                    break;
+                case Contents.CHAT_TYPE_VIDEO_L_INT:
+                    // TODO: 2016/11/25
+                    view = mInflater.inflate(R.layout.chat_vid_item_1, viewGroup, false);
+                    videoHodlerL = new VideoHodlerL();
+                    videoHodlerL.videoView = (ChatSurfaceView) view.findViewById(R.id.chat_video);
+                    videoHodlerL.videoMask = (ImageView) view.findViewById(R.id.video_mask);
+                    videoHodlerL.playBtn = (ImageButton) view.findViewById(R.id.video_mask_play);
+                    view.setTag(videoHodlerL);
+                    break;
             }
         } else {
             switch (type) {
-                case Config.INT_TYPE_TXT_L:
+                case Contents.CHAT_TYPE_TEXT_L_INT:
                     txtHolderL = (TxtHolderL) view.getTag();
                     break;
-                case Config.INT_TYPE_TXT_R:
+
+                case Contents.CHAT_TYPE_TEXT_R_INT:
                     txtHolderR = (TxtHolderR) view.getTag();
                     break;
-                case Config.INT_TYPE_PIC_L:
+
+                case Contents.CHAT_TYPE_IMAGE_L_INT:
                     picHolderL = (PicHolderL) view.getTag();
                     break;
-                case Config.INT_TYPE_PIC_R:
+
+                case Contents.CHAT_TYPE_IMAGE_R_INT:
                     picHolderR = (PicHolderR) view.getTag();
                     break;
-                case Config.INT_TYPE_AUDIO_L:
+
+                case Contents.CHAT_TYPE_AUDIO_L_INT:
                     audioHolderL = (AudioHolderL) view.getTag();
                     break;
-                case Config.INT_TYPE_AUDIO_R:
+
+                case Contents.CHAT_TYPE_AUDIO_R_INT:
                     audioHolderR = (AudioHolderR) view.getTag();
                     break;
+
+                case Contents.CHAT_TYPE_VIDEO_R_INT:
+                    videoHodlerR = (VideoHodlerR) view.getTag();
+                    break;
+
+                case Contents.CHAT_TYPE_VIDEO_L_INT:
+                    videoHodlerL = (VideoHodlerL) view.getTag();
+                    break;
             }
         }
         switch (type) {
-            case Config.INT_TYPE_TXT_L:
+            case Contents.CHAT_TYPE_TEXT_L_INT:
                 txtHolderL.text.setText(item.getText());
                 break;
-            case Config.INT_TYPE_TXT_R:
+            case Contents.CHAT_TYPE_TEXT_R_INT:
                 txtHolderR.text.setText(item.getText());
                 break;
-            case Config.INT_TYPE_PIC_L:
-                picHolderL.pic.setImageFile(item.getText());
-                picHolderL.pic.setTag(R.id.TAG_IMAGE_FILE_PATH,item.getText());
+            case Contents.CHAT_TYPE_IMAGE_L_INT:
+                if (mPicLruCache.get(item.getText()) == null) {
+                    picHolderL.pic.setImageFile(mResolver, mPicLruCache, item.getText());
+                } else {
+                    picHolderL.pic.setImageBitmap(mPicLruCache.get(item.getText()));
+                }
+                picHolderL.pic.setTag(R.id.TAG_IMAGE_FILE_PATH, item.getText());
                 picHolderL.pic.setOnClickListener(mOnImageClickListener);
+                switch (item.getSendStatus()) {
+                    case Contents.MESSAGE_STATUS_SENT:
+                        picHolderL.progressBar.setVisibility(ProgressBar.INVISIBLE);
+                        break;
+                    case Contents.MESSAGE_STATUS_SENDING:
+                        picHolderL.progressBar.setVisibility(ProgressBar.VISIBLE);
+                        break;
+                }
                 break;
-            case Config.INT_TYPE_PIC_R:
-                picHolderR.pic.setImageFile(item.getText());
-                picHolderR.pic.setTag(R.id.TAG_IMAGE_FILE_PATH,item.getText());
+            case Contents.CHAT_TYPE_IMAGE_R_INT:
+                Log.i(TAG, item.getText());
+                if (mPicLruCache.get(item.getText()) == null) {
+                    picHolderR.pic.setImageFile(mResolver, mPicLruCache, item.getText());
+                } else {
+                    picHolderR.pic.setImageBitmap(mPicLruCache.get(item.getText()));
+                }
+                picHolderR.pic.setTag(R.id.TAG_IMAGE_FILE_PATH, item.getText());
                 picHolderR.pic.setOnClickListener(mOnImageClickListener);
+                switch (item.getSendStatus()) {
+                    case Contents.MESSAGE_STATUS_SENT:
+                        picHolderR.progressBar.setVisibility(ProgressBar.INVISIBLE);
+                        break;
+                    case Contents.MESSAGE_STATUS_SENDING:
+                        picHolderR.progressBar.setVisibility(ProgressBar.VISIBLE);
+                        break;
+                }
                 break;
-            case Config.INT_TYPE_AUDIO_L:
+            case Contents.CHAT_TYPE_AUDIO_L_INT:
                 audioHolderL.time.setText(item.getAudioLength() + "\"");
                 audioHolderL.filePath.setText(item.getText());
                 audioHolderL.recorder_len.setOnClickListener(mOnAudioClickListener);
                 break;
-            case Config.INT_TYPE_AUDIO_R:
+            case Contents.CHAT_TYPE_AUDIO_R_INT:
                 audioHolderR.time.setText(item.getAudioLength() + "\"");
                 audioHolderR.filePath.setText(item.getText());
                 audioHolderR.recorder_len.setOnClickListener(mOnAudioClickListener);
                 break;
+            case Contents.CHAT_TYPE_VIDEO_R_INT:
+                videoHodlerR.videoView.setVideoPath(videoHodlerR.videoMask, videoHodlerR.playBtn, mPicLruCache, item.getText());
+                videoHodlerR.videoView.setOnClickListener(mOnVideoClickListener);
+                videoHodlerR.videoView.setOnDoubleClickListener(mOnVideoDoubleClickListener);
+
+                break;
+            case Contents.CHAT_TYPE_VIDEO_L_INT:
+                videoHodlerL.videoView.setVideoPath(videoHodlerL.videoMask, videoHodlerL.playBtn, mPicLruCache, item.getText());
+                videoHodlerL.videoView.setOnClickListener(mOnVideoClickListener);
+                videoHodlerL.videoView.setOnDoubleClickListener(mOnVideoDoubleClickListener);
+                break;
         }
+        mViews.put(i, view);
         return view;
     }
 
+    //文本类型详细Holder 显示在左边
     class TxtHolderL {
         ImageView head;
         TextView text;
     }
 
+    //文本类型消息Holder 显示在右边
     class TxtHolderR {
         ImageView head;
         TextView text;
     }
 
-    class PicHolderL {
+    //图片类型消息Holder 显示左边
+    public class PicHolderL {
         ImageView head;
-        ChatImageView pic;
+        public ChatImageView pic;
+        public ProgressBar progressBar;
     }
 
-    class PicHolderR {
+    //图片类型消息Holder 显示在右边
+    public class PicHolderR {
         ImageView head;
         ChatImageView pic;
+        public ProgressBar progressBar;
     }
 
+    //音频类型消息Holder 显示在左边
     class AudioHolderL {
         ImageView head;
         TextView time;
@@ -222,17 +375,32 @@ public class ChatAdapter extends BaseAdapter {
         FrameLayout recorder_len;
     }
 
+    //音频类型消息Holder 显示在右边
     class AudioHolderR {
         ImageView head;
         TextView time;
         TextView filePath;
         FrameLayout recorder_len;
     }
-    public void finish(){
-        if (mDatas.size()>0){
-            ChatMessageItem item = mDatas.get(mDatas.size()-1);
-            Log.i(TAG,"finish()---"+item.getFromUserName());
-            Log.i(TAG,item.getType()+"");
+
+    class VideoHodlerR {
+        ChatSurfaceView videoView;
+        ImageView videoMask;
+        ImageButton playBtn;
+    }
+
+    class VideoHodlerL {
+        ChatSurfaceView videoView;
+        ImageView videoMask;
+        ImageButton playBtn;
+    }
+
+    //更新聊天主窗口
+    public void finish() {
+        if (mDatas.size() > 0) {
+            ChatMessageItem item = mDatas.get(mDatas.size() - 1);
+            Log.i(TAG, "finish()---" + item.getFromUserName());
+            Log.i(TAG, item.getType() + "");
             mDataBaseManager.updateMainMessageItem(item);
         }
     }
index befac65..293d401 100644 (file)
@@ -18,10 +18,12 @@ import cc.minsnail.beans.YgUser;
 public class FriendsAdapter extends BaseAdapter {
     private Context mContext;
     private List<YgUser> mRoster;
-    public FriendsAdapter(Context context,List<YgUser> f){
+
+    public FriendsAdapter(Context context, List<YgUser> f) {
         this.mContext = context;
-        this.mRoster=f;
+        this.mRoster = f;
     }
+
     @Override
     public int getCount() {
         return mRoster.size();
@@ -40,13 +42,13 @@ public class FriendsAdapter extends BaseAdapter {
     @Override
     public View getView(int i, View view, ViewGroup viewGroup) {
         Holder holder = null;
-        if (view == null){
-            view = LayoutInflater.from(mContext).inflate(R.layout.roster_item,viewGroup,false);
+        if (view == null) {
+            view = LayoutInflater.from(mContext).inflate(R.layout.roster_item, viewGroup, false);
             holder = new Holder();
             holder.jid = (TextView) view.findViewById(R.id.user_jid);
             holder.name = (TextView) view.findViewById(R.id.name);
             view.setTag(holder);
-        }else {
+        } else {
             holder = (Holder) view.getTag();
         }
 //        if (friends.get(i).getCode()!=200){
@@ -58,7 +60,8 @@ public class FriendsAdapter extends BaseAdapter {
 
         return view;
     }
-    static class Holder{
+
+    static class Holder {
         TextView jid;
         TextView name;
     }
index 4976ad5..8d49515 100644 (file)
@@ -19,6 +19,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import cc.minsnail.Contents;
 import cc.minsnail.beans.ChatMessageItem;
 import cc.minsnail.beans.MainMessageItem;
 import cc.minsnail.config.Config;
@@ -38,11 +39,13 @@ public class MessageAdapter extends BaseAdapter {
     private LayoutInflater mInflater;
     private DataBaseManager mDataBaseManager;
 
-    public interface OnMainMessageItemClickListener{
-        void onItemClick(MainMessageItem item,int position);
+    public interface OnMainMessageItemClickListener {
+        void onItemClick(MainMessageItem item, int position);
     }
+
     private OnMainMessageItemClickListener mOnMainMessageItemClickListener;
-    public MessageAdapter(Context context, List<MainMessageItem> datas,ListView view) {
+
+    public MessageAdapter(Context context, List<MainMessageItem> datas, ListView view) {
         mContext = context;
         mDatas = datas;
         mMessageView = view;
@@ -55,15 +58,17 @@ public class MessageAdapter extends BaseAdapter {
         mMessageView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
-                if (mOnMainMessageItemClickListener!=null){
-                    mOnMainMessageItemClickListener.onItemClick(mDatas.get(i),i);
+                if (mOnMainMessageItemClickListener != null) {
+                    mOnMainMessageItemClickListener.onItemClick(mDatas.get(i), i);
                 }
             }
         });
     }
-    public void setOnMainMessageItemClickListener(OnMainMessageItemClickListener listener){
+
+    public void setOnMainMessageItemClickListener(OnMainMessageItemClickListener listener) {
         mOnMainMessageItemClickListener = listener;
     }
+
     private void initUsersMap() {
         for (MainMessageItem item : mDatas) {
             if (!mUsers.containsKey(item.getFromUserName())) {
@@ -73,7 +78,7 @@ public class MessageAdapter extends BaseAdapter {
     }
 
     public void addMessage(MainMessageItem item) {
-        Log.i(TAG, "add main message "+item.getToUserName());
+        Log.i(TAG, "add main message " + item.getToUserName());
         if (mUsers.containsKey(item.getFromUserName())) {
             ((MainMessageItem) mUsers.get(item.getFromUserName())).setText(item.getText());
         } else {
@@ -84,7 +89,7 @@ public class MessageAdapter extends BaseAdapter {
         notifyDataSetChanged();
     }
 
-    public void deleteMainMessageItem(int position){
+    public void deleteMainMessageItem(int position) {
         mUsers.remove(mDatas.get(position));
         mDatas.remove(position);
         notifyDataSetChanged();
@@ -105,13 +110,6 @@ public class MessageAdapter extends BaseAdapter {
         return i;
     }
 
-    private static final int INT_TYPE_TXT_L = 0;
-    private static final int INT_TYPE_TXT_R = 1;
-    private static final int INT_TYPE_PIC_L = 2;
-    private static final int INT_TYPE_PIC_R = 3;
-    private static final int INT_TYPE_AUDIO_L = 4;
-    private static final int INT_TYPE_AUDIO_R = 5;
-
     @Override
     public View getView(int i, View view, ViewGroup viewGroup) {
         MainMessageItem item = mDatas.get(i);
@@ -129,17 +127,21 @@ public class MessageAdapter extends BaseAdapter {
             holder = (Holder) view.getTag();
         }
         switch (item.getType()) {
-            case INT_TYPE_TXT_L:
-            case INT_TYPE_TXT_R:
+            case Contents.CHAT_TYPE_TEXT_L_INT:
+            case Contents.CHAT_TYPE_TEXT_R_INT:
                 holder.text.setText(item.getText());
                 break;
-            case INT_TYPE_PIC_L:
-            case INT_TYPE_PIC_R:
-                holder.text.setText("[图片]");
+            case Contents.CHAT_TYPE_IMAGE_L_INT:
+            case Contents.CHAT_TYPE_IMAGE_R_INT:
+                holder.text.setText(R.string.str_message_image_tag);
+                break;
+            case Contents.CHAT_TYPE_AUDIO_L_INT:
+            case Contents.CHAT_TYPE_AUDIO_R_INT:
+                holder.text.setText(R.string.str_message_audio_tag);
                 break;
-            case INT_TYPE_AUDIO_L:
-            case INT_TYPE_AUDIO_R:
-                holder.text.setText("[语音]");
+            case Contents.CHAT_TYPE_VIDEO_L_INT:
+            case Contents.CHAT_TYPE_VIDEO_R_INT:
+                holder.text.setText(R.string.str_message_video_tag);
                 break;
         }
         holder.jid.setText(item.getFromJid());
index fb3a702..81d2674 100644 (file)
@@ -11,28 +11,37 @@ import org.jivesoftware.smack.packet.XMPPError;
 public class YgInfo implements Parcelable {
     private int code;
     private String body;
-    public YgInfo(){}
-    public void setCode(int code){
+
+    public YgInfo() {
+    }
+
+    public void setCode(int code) {
         this.code = code;
     }
-    public void setBody(String body){
+
+    public void setBody(String body) {
         this.body = body;
     }
-    public int getCode(){
+
+    public int getCode() {
         return this.code;
     }
-    public String getBody(){
+
+    public String getBody() {
         return this.body;
     }
-    public YgInfo(int code,String body){
+
+    public YgInfo(int code, String body) {
         this.code = code;
         this.body = body;
     }
-    public YgInfo getFromXMPPError(XMPPError xmppError){
+
+    public YgInfo getFromXMPPError(XMPPError xmppError) {
         this.code = xmppError.getCode();
         this.body = xmppError.getMessage();
         return this;
     }
+
     private YgInfo(Parcel in) {
         this.code = in.readInt();
         this.body = in.readString();
@@ -60,7 +69,8 @@ public class YgInfo implements Parcelable {
         parcel.writeInt(this.code);
         parcel.writeString(this.body);
     }
-    public String toJson(){
-        return "{\"code\":"+code+",\"body\":"+body+"}";
+
+    public String toJson() {
+        return "{\"code\":" + code + ",\"body\":" + body + "}";
     }
 }
index 4bce92f..328067b 100644 (file)
@@ -14,7 +14,10 @@ public class YgMessage implements Parcelable {
     private String type;
     private String body;
     private int custom;
-    public YgMessage(){}
+
+    public YgMessage() {
+    }
+
     public void setBody(String body) {
         this.body = body;
     }
@@ -31,9 +34,10 @@ public class YgMessage implements Parcelable {
         this.type = type;
     }
 
-    public void setCustom(int isCustom){
+    public void setCustom(int isCustom) {
         this.custom = isCustom;
     }
+
     public String getBody() {
         return body;
     }
@@ -49,16 +53,19 @@ public class YgMessage implements Parcelable {
     public String getType() {
         return type;
     }
-    public int getCustom(){
+
+    public int getCustom() {
         return custom;
     }
-    public YgMessage getFromMessage(Message message){
+
+    public YgMessage getFromMessage(Message message) {
         this.setTo(message.getTo());
         this.setFrom(message.getFrom());
         this.setBody(message.getBody());
         this.setType(message.getType().toString());
         return this;
     }
+
     protected YgMessage(Parcel in) {
         this.to = in.readString();
         this.from = in.readString();
@@ -78,10 +85,12 @@ public class YgMessage implements Parcelable {
             return new YgMessage[size];
         }
     };
+
     @Override
     public int describeContents() {
         return 0;
     }
+
     @Override
     public void writeToParcel(Parcel parcel, int i) {
         parcel.writeString(this.to);
@@ -90,7 +99,8 @@ public class YgMessage implements Parcelable {
         parcel.writeString(this.body);
         parcel.writeInt(this.custom);
     }
-    public String toJson(){
-        return "{\"to\":"+to+",\"from\":"+from+",\"body\":"+body+",\"type\":"+type+"}";
+
+    public String toJson() {
+        return "{\"to\":" + to + ",\"from\":" + from + ",\"body\":" + body + ",\"type\":" + type + "}";
     }
 }
index 2a149a4..300a14b 100644 (file)
@@ -7,6 +7,7 @@ import org.json.JSONObject;
 
 import java.io.File;
 
+import cc.minsnail.Contents;
 import cc.minsnail.config.Config;
 import cc.minsnail.tools.Utils;
 
@@ -19,29 +20,32 @@ public class YgText {
     private String body;
     private long length;
     private JSONObject json;
-    public YgText(){
+
+    public YgText() {
 
     }
 
-    public YgText(String type,String body,long length){
+    public YgText(String type, String body, long length) {
         this.type = type;
         this.body = body;
         this.length = length;
     }
-    public String toJson(){
+
+    public String toJson() {
         json = new JSONObject();
         try {
-            json.put("type",type);
-            json.put("body",body);
-            json.put("length",length);
+            json.put("type", type);
+            json.put("body", body);
+            json.put("length", length);
         } catch (JSONException e) {
             e.printStackTrace();
             return null;
         }
         return json.toString();
     }
-    public YgText createFromJson(String jsonString){
-        if (jsonString==null|"".equals(jsonString.trim())) return null;
+
+    public YgText createFromJson(String jsonString) {
+        if (jsonString == null | "".equals(jsonString.trim())) return null;
         try {
             json = new JSONObject(jsonString);
             type = json.getString("type");
@@ -53,24 +57,25 @@ public class YgText {
         }
         return this;
     }
-    public File createFile(){
+
+    public File createFile() {
         try {
-            if (type.equals("txt")) return null;
+            if (type.equals(Contents.STR_MESSAGE_TYPE_TEXT)) return null;
             JSONObject object = new JSONObject(body);
             File divce = Environment.getExternalStorageDirectory();
             File appPath = new File(divce, Config.APP_PATH);
-            switch (type){
-                case "pic":
+            switch (type) {
+                case Contents.STR_MESSAGE_TYPE_IMAGE:
                     File picPath = new File(appPath, Config.PIC_PATH);
                     if (!picPath.exists()) picPath.mkdirs();
-                    File file = new File(picPath,object.getString("fileName"));
-                    if (Utils.string2file(object.getString("data"),file))return file;
+                    File file = new File(picPath, object.getString("fileName"));
+                    if (Utils.string2file(object.getString("data"), file)) return file;
                     break;
-                case "audio":
+                case Contents.STR_MESSAGE_TYPE_AUDIO:
                     File audioPath = new File(appPath, Config.AUDIO_PATH);
                     if (!audioPath.exists()) audioPath.mkdirs();
-                    File audioFile = new File(audioPath,object.getString("fileName"));
-                    if (Utils.string2file(object.getString("data"),audioFile)) return audioFile;
+                    File audioFile = new File(audioPath, object.getString("fileName"));
+                    if (Utils.string2file(object.getString("data"), audioFile)) return audioFile;
                     break;
                 default:
                     break;
@@ -81,6 +86,7 @@ public class YgText {
         }
         return null;
     }
+
     public void setBody(String body) {
         this.body = body;
     }
@@ -89,7 +95,7 @@ public class YgText {
         this.type = type;
     }
 
-    public void setLength(Long length){
+    public void setLength(Long length) {
         this.length = length;
     }
 
@@ -101,7 +107,7 @@ public class YgText {
         return type;
     }
 
-    public long getLength(){
+    public long getLength() {
         return length;
     }
 
index 52f16fe..7f4f9f1 100644 (file)
@@ -18,21 +18,27 @@ public class YgTreeNode {
     //是否展开
     private boolean isExpand = false;
     private YgTreeNode parent;
-    public YgTreeNode(){}
-    public YgTreeNode(int id,int pid,String name){
+
+    public YgTreeNode() {
+    }
+
+    public YgTreeNode(int id, int pid, String name) {
         this.id = id;
         this.pid = pid;
         this.name = name;
     }
-    public boolean isRoot(){
-        if(pid == -1) return false;
+
+    public boolean isRoot() {
+        if (pid == -1) return false;
         return parent == null;
     }
-    public boolean isParentExpand(){
+
+    public boolean isParentExpand() {
         if (parent == null) return false;
         return parent.isExpand();
     }
-    public boolean isLeaf(){
+
+    public boolean isLeaf() {
         return children.size() == 0;
     }
 
@@ -60,15 +66,15 @@ public class YgTreeNode {
 
     public void setExpand(boolean expand) {
         isExpand = expand;
-        if (!isExpand){
-            for (YgTreeNode node:children){
+        if (!isExpand) {
+            for (YgTreeNode node : children) {
                 node.setExpand(false);
             }
         }
     }
 
     public int getLevel() {
-        return parent == null ?0:parent.getLevel() + 1;
+        return parent == null ? 0 : parent.getLevel() + 1;
     }
 
     public void setLevel(int level) {
@@ -108,7 +114,7 @@ public class YgTreeNode {
     }
 
     public String getUserName() {
-        if (userName==null)return jid.split("@")[0];
+        if (userName == null) return jid.split("@")[0];
         return userName;
     }
 
index 728b0b5..9ab42ab 100644 (file)
@@ -10,7 +10,7 @@ import cc.minsnail.annotation.TreeNodePid;
 /**
  * Created by yg on 2016/9/27.
  */
-public class YgUser extends YgInfo implements Parcelable{
+public class YgUser extends YgInfo implements Parcelable {
     private int id;
     private int pid;
     private String jid;
@@ -28,93 +28,100 @@ public class YgUser extends YgInfo implements Parcelable{
     private String misc;
     private String text;
     private String remove;
-    public YgUser(){}
-    public void setId(int id){
+
+    public YgUser() {
+    }
+
+    public void setId(int id) {
         this.id = id;
     }
-    public void setPid(int pid){
+
+    public void setPid(int pid) {
         this.pid = pid;
     }
-    public void setJid(String jid){
+
+    public void setJid(String jid) {
         this.jid = jid;
     }
 
-    public void setUsername(String username){
+    public void setUsername(String username) {
         this.username = username;
     }
 
-    public void setName(String name){
+    public void setName(String name) {
         this.name = name;
     }
 
-    public void setFirstName(String firstName){
+    public void setFirstName(String firstName) {
         this.firstName = firstName;
     }
 
-    public void setLastName(String lastName){
+    public void setLastName(String lastName) {
         this.lastName = lastName;
     }
 
-    public void setEmail(String email){
+    public void setEmail(String email) {
         this.email = email;
     }
 
-    public void setCity(String city){
+    public void setCity(String city) {
         this.city = city;
     }
 
-    public void setState(String state){
+    public void setState(String state) {
         this.state = state;
     }
 
-    public void setZip(String zip){
+    public void setZip(String zip) {
         this.zip = zip;
     }
 
-    public void setPhone(String phone){
+    public void setPhone(String phone) {
         this.phone = phone;
     }
 
-    public void setUrl(String url){
+    public void setUrl(String url) {
         this.url = url;
     }
 
-    public void setDate(String date){
+    public void setDate(String date) {
         this.date = date;
     }
 
-    public void setMisc(String misc){
+    public void setMisc(String misc) {
         this.misc = misc;
     }
 
-    public void setText(String text){
+    public void setText(String text) {
         this.text = text;
     }
 
-    public void setRemove(String remove){
+    public void setRemove(String remove) {
         this.remove = remove;
     }
 
-    public int getId(){
+    public int getId() {
         return id;
     }
-    public int getPid(){
+
+    public int getPid() {
         return pid;
     }
-    public String getJid(){
+
+    public String getJid() {
         return jid;
     }
 
-    public String getUsername(){
+    public String getUsername() {
         return username;
     }
 
-    public String getName(){
-        if (name==null)return jid.split("@")[0];
+    public String getName() {
+        if (name == null) return jid.split("@")[0];
         return name;
     }
 
-    public String getFirstName(){
+    public String getFirstName() {
         return firstName;
     }
 
@@ -126,7 +133,7 @@ public class YgUser extends YgInfo implements Parcelable{
         return email;
     }
 
-    public String getCity(){
+    public String getCity() {
         return city;
     }
 
@@ -161,6 +168,7 @@ public class YgUser extends YgInfo implements Parcelable{
     public String getZip() {
         return zip;
     }
+
     private YgUser(Parcel in) {
         id = in.readInt();
         pid = in.readInt();
@@ -218,7 +226,8 @@ public class YgUser extends YgInfo implements Parcelable{
         parcel.writeString(text);
         parcel.writeString(remove);
     }
-    public String toJson(){
-        return "{\"jid\":"+jid+",\"name\":"+name+",\"firstname\":"+firstName+"}";
+
+    public String toJson() {
+        return "{\"jid\":" + jid + ",\"name\":" + name + ",\"firstname\":" + firstName + "}";
     }
 }
index 42bf467..718ba4a 100644 (file)
@@ -24,7 +24,9 @@ public class YgUserConfig implements Parcelable {
     private int changeStatus;
     private int regType;
     private int delStatus;
-    public YgUserConfig(){}
+
+    public YgUserConfig() {
+    }
 
     protected YgUserConfig(Parcel in) {
         username = in.readString();
index cec415a..dba12dc 100644 (file)
@@ -6,8 +6,8 @@ import org.jivesoftware.smack.packet.IQ;
  * Created by yg on 2016/10/15.
  */
 public class YgUserIQ extends IQ {
-    private static final String ELEMENT="register";
-    private static final String NAMESPACE="yg:iq:register";
+    private static final String ELEMENT = "register";
+    private static final String NAMESPACE = "yg:iq:register";
     private String username;
     private String password;
     private String name;
@@ -25,12 +25,14 @@ public class YgUserIQ extends IQ {
     private int changeStatus;
     private int regType;
     private int delStatus;
-    public YgUserIQ(Type type){
+
+    public YgUserIQ(Type type) {
         this.setType(type);
     }
-    public YgUserIQ addYgUserConfig(YgUserConfig config){
-        if (config.getUsername()!=null) username = config.getUsername();
-        if (config.getPassword()!=null) password = config.getPassword();
+
+    public YgUserIQ addYgUserConfig(YgUserConfig config) {
+        if (config.getUsername() != null) username = config.getUsername();
+        if (config.getPassword() != null) password = config.getPassword();
         name = config.getName();
         email = config.getEmail();
         sex = config.getSex();
@@ -40,6 +42,7 @@ public class YgUserIQ extends IQ {
         mobile = config.getMobile();
         return this;
     }
+
     public void setAllowEmailSearch(boolean allowEmailSearch) {
         this.allowEmailSearch = allowEmailSearch;
     }
@@ -105,7 +108,7 @@ public class YgUserIQ extends IQ {
     }
 
     public String getBirth() {
-        if (birth==null) birth="0000000000";
+        if (birth == null) birth = "0000000000";
         return birth;
     }
 
@@ -114,7 +117,7 @@ public class YgUserIQ extends IQ {
     }
 
     public String getDate() {
-        if (date==null)date = ""+System.currentTimeMillis();
+        if (date == null) date = "" + System.currentTimeMillis();
         return date;
     }
 
@@ -181,8 +184,8 @@ public class YgUserIQ extends IQ {
     @Override
     public String getChildElementXML() {
         StringBuffer sb = new StringBuffer();
-        sb.append("<"+ELEMENT+" xmlns=\""+NAMESPACE+"\">");
-        if (getType()==Type.SET){
+        sb.append("<" + ELEMENT + " xmlns=\"" + NAMESPACE + "\">");
+        if (getType() == Type.SET) {
             sb.append("<username>").append(getUsername()).append("</username>");
             sb.append("<password>").append(getPassword()).append("</password>");
             sb.append("<name>").append(getName()).append("</name>");
@@ -201,7 +204,7 @@ public class YgUserIQ extends IQ {
             sb.append("<regtype>").append(getRegType()).append("</regtype>");
             sb.append("<delstatus>").append(getDelStatus()).append("</delstatus>");
         }
-        sb.append("</"+ELEMENT+">");
+        sb.append("</" + ELEMENT + ">");
         return sb.toString();
     }
 }
index 86f174f..48d79ab 100644 (file)
@@ -11,25 +11,33 @@ public class YgVCard extends YgInfo implements Parcelable {
     private String firstName;
     private String lastName;
 
-    public YgVCard(){}
-    public void setUser(String user){
+    public YgVCard() {
+    }
+
+    public void setUser(String user) {
         this.user = user;
     }
-    public void setFirstName(String firstName){
+
+    public void setFirstName(String firstName) {
         this.firstName = firstName;
     }
-    public void setLastName(String lastName){
+
+    public void setLastName(String lastName) {
         this.lastName = lastName;
     }
-    public String getUser(){
+
+    public String getUser() {
         return user;
     }
-    public String getFirstName(){
+
+    public String getFirstName() {
         return firstName;
     }
-    public String getLastName(){
+
+    public String getLastName() {
         return lastName;
     }
+
     private YgVCard(Parcel in) {
         this.user = in.readString();
         this.firstName = in.readString();
@@ -59,7 +67,8 @@ public class YgVCard extends YgInfo implements Parcelable {
         parcel.writeString(firstName);
         parcel.writeString(lastName);
     }
-    public String toJson(){
-        return "{\"user\":"+user+",\"firstName\":"+firstName+",\"lastName\":"+lastName+"}";
+
+    public String toJson() {
+        return "{\"user\":" + user + ",\"firstName\":" + firstName + ",\"lastName\":" + lastName + "}";
     }
 }
index 07f94fe..17a94c5 100644 (file)
@@ -12,10 +12,11 @@ public class Config {
     public static final String APP_PATH = "smackclient";
     public static final String PIC_PATH = "pic";
     public static final String AUDIO_PATH = "audio";
+    public static final String VIDEO_PATH = "video";
     public static final int BITMAP_SIZE = 100;//k
     //SQLite
     public static final String DATABASE_NAME = "SmackClient.db";
-    public static final int DATABASE_VERSION = 4;
+    public static final int DATABASE_VERSION = 5;
 
     public static final String TIME_FORMAT = "HH:mm";
 
@@ -26,6 +27,7 @@ public class Config {
     public static final String KEY_FROM_USERNAME = "fromUserName";
     public static final String KEY_FROM_JID = "fromJid";
     public static final String KEY_FROM_NAME = "fromName";
+    public static final String KEY_MESSAGE_PIC = "picPath";
 
     public static final String OSS_ENDPOINT = "oss-cn-shanghai.aliyuncs.com";
     public static final String OSS_ACCESS_KEY_ID = "lHtglO8uAweVCN4G";
@@ -34,11 +36,7 @@ public class Config {
     public static final String OSS_BUCKET_NAME = "smackclient";
 
 
+    public static final String CLIENT_SERVER_ACTION_DOWNLOAD_PIC = "downloadpic";
 
-    public static final int INT_TYPE_TXT_L = 0;
-    public static final int INT_TYPE_TXT_R = 1;
-    public static final int INT_TYPE_PIC_L = 2;
-    public static final int INT_TYPE_PIC_R = 3;
-    public static final int INT_TYPE_AUDIO_L = 4;
-    public static final int INT_TYPE_AUDIO_R = 5;
+    public static final String SHARED_PREFERENCE_FILE_KEY = "cc.minsnail.smackclient.SHARED_MY";
 }
index a0beae4..18fedae 100644 (file)
@@ -32,6 +32,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 
+import cc.minsnail.Contents;
 import cc.minsnail.activity.ChatActivity;
 import cc.minsnail.adapter.MessageAdapter;
 import cc.minsnail.aidl.IServiceAidlInterface;
@@ -73,7 +74,7 @@ public class MessageFragment extends Fragment {
         super.onAttach(context);
         mContext = context;
         mDataBaseManager = DataBaseManager.getInstance(mContext);
-        mSharedHelper = new SharedHelper(mContext);
+        mSharedHelper = SharedHelper.getInstance(mContext);
         mOssManager = OssManager.getInstance(mContext);
         Log.i(TAG, "onAttach");
     }
@@ -167,7 +168,7 @@ public class MessageFragment extends Fragment {
             YgMessage ygMessage = intent.getParcelableExtra("msg");
             Log.i(TAG, "received message");
             MainMessageItem item = new MainMessageItem(ygMessage);
-            if (item.getType() == Config.INT_TYPE_PIC_L) {
+            if (item.getType() == Contents.CHAT_TYPE_IMAGE_L_INT) {
                 ossLoadImage(item);
             } else {
                 mDataBaseManager.insertChatMessageItem(item);
index eec1b23..f6407e9 100644 (file)
@@ -72,7 +72,7 @@ public class RosterFragment extends Fragment {
                 public void onClick(YgTreeNode node, int position) {
                     Intent intent = new Intent(mContext, UserSummaryActivity.class);
                     intent.putExtra(Config.KEY_FROM_JID, node.getJid());
-                    intent.putExtra(Config.KEY_FROM_NAME,node.getName());
+                    intent.putExtra(Config.KEY_FROM_NAME, node.getName());
                     startActivity(intent);
                 }
             });
@@ -9,43 +9,48 @@ import java.util.UUID;
 /**
  * Created by yg on 2016/10/25.
  */
-public class AudioManager {
+public class AudioRecorderManager {
     private MediaRecorder mMediaRecorder;
     private String mDir;
-    private String mCurrentFilePath;
-    private static AudioManager mInstance;
+    private String mCurrentAudioFilePath;
+    private static AudioRecorderManager mInstance;
     private boolean isPrepared;
 
-    private AudioManager(String dir){
+    private AudioRecorderManager(String dir) {
         mDir = dir;
     }
-    public interface AudioStateListener{
+
+    public interface AudioStateListener {
         void wellPrepare();
     }
+
     public AudioStateListener mListener;
-    public void setAudioStateListener(AudioStateListener listener){
+
+    public void setAudioStateListener(AudioStateListener listener) {
         mListener = listener;
     }
-    public static AudioManager getInstance(String dir){
-        if (mInstance == null){
-            synchronized (AudioManager.class){
-                if (mInstance == null){
-                    mInstance = new AudioManager(dir);
+
+    public static AudioRecorderManager getInstance(String dir) {
+        if (mInstance == null) {
+            synchronized (AudioRecorderManager.class) {
+                if (mInstance == null) {
+                    mInstance = new AudioRecorderManager(dir);
                 }
             }
         }
         return mInstance;
     }
-    public void prepareAudio(){
+
+    public void prepareAudio() {
         try {
             isPrepared = false;
             File dir = new File(mDir);
-            if (!dir.exists()){
+            if (!dir.exists()) {
                 dir.mkdirs();
             }
-            String fileName = generateFileName();
-            File file = new File(dir,fileName);
-            mCurrentFilePath = file.getAbsolutePath();
+            String fileName = generateAudioFileName();
+            File file = new File(dir, fileName);
+            mCurrentAudioFilePath = file.getAbsolutePath();
             mMediaRecorder = new MediaRecorder();
             mMediaRecorder.setOutputFile(file.getAbsolutePath());
 
@@ -59,7 +64,7 @@ public class AudioManager {
 
             mMediaRecorder.start();
             isPrepared = true;
-            if (mListener!=null){
+            if (mListener != null) {
                 mListener.wellPrepare();
             }
         } catch (IOException e) {
@@ -67,35 +72,38 @@ public class AudioManager {
         }
     }
 
-    private String generateFileName() {
-        return UUID.randomUUID().toString()+".amr";
+    private String generateAudioFileName() {
+        return UUID.randomUUID().toString() + ".amr";
     }
 
-    public int getVoiceLevel(int maxLevel){
-        if (isPrepared){
+    public int getVoiceLevel(int maxLevel) {
+        if (isPrepared) {
             try {
                 //mMediaRecorder.getMaxAmplitude() 1-32767
-                return maxLevel * mMediaRecorder.getMaxAmplitude()/32768 + 1;
-            }catch (Exception e){
+                return maxLevel * mMediaRecorder.getMaxAmplitude() / 32768 + 1;
+            } catch (Exception e) {
 
             }
         }
         return 1;
     }
-    public void release(){
+
+    public void release() {
         mMediaRecorder.stop();
         mMediaRecorder.release();
         mMediaRecorder = null;
     }
-    public void cancel(){
+
+    public void cancel() {
         release();
-        if (mCurrentFilePath != null){
-            File file = new File(mCurrentFilePath);
+        if (mCurrentAudioFilePath != null) {
+            File file = new File(mCurrentAudioFilePath);
             file.delete();
-            mCurrentFilePath = null;
+            mCurrentAudioFilePath = null;
         }
     }
-    public String getCurrentFilePath(){
-        return mCurrentFilePath;
+
+    public String getCurrentAudioFilePath() {
+        return mCurrentAudioFilePath;
     }
 }
index aae34b3..6ecabf5 100644 (file)
@@ -20,21 +20,23 @@ public class DialogManager {
     private TextView mLable;
     private Context mContext;
 
-    public DialogManager(Context context){
+    public DialogManager(Context context) {
         mContext = context;
     }
-    public void showRecordingDialog(){
+
+    public void showRecordingDialog() {
         mDialog = new Dialog(mContext, R.style.Theme_AudioDialog);
         LayoutInflater inflater = LayoutInflater.from(mContext);
-        View view = inflater.inflate(R.layout.dialog_recorder,null);
+        View view = inflater.inflate(R.layout.dialog_recorder, null);
         mDialog.setContentView(view);
         mIcon = (ImageView) mDialog.findViewById(R.id.recorder_dialog_icon);
         mVoice = (ImageView) mDialog.findViewById(R.id.recorder_diallog_voice);
         mLable = (TextView) mDialog.findViewById(R.id.recoder_dialog_lable);
         mDialog.show();
     }
-    public void recording(){
-        if (mDialog!=null && mDialog.isShowing()){
+
+    public void recording() {
+        if (mDialog != null && mDialog.isShowing()) {
             mIcon.setVisibility(View.VISIBLE);
             mVoice.setVisibility(View.VISIBLE);
             mLable.setVisibility(View.VISIBLE);
@@ -43,8 +45,9 @@ public class DialogManager {
             mLable.setText("手指上划 取消发送");
         }
     }
-    public void wantToCancel(){
-        if (mDialog!=null && mDialog.isShowing()){
+
+    public void wantToCancel() {
+        if (mDialog != null && mDialog.isShowing()) {
             mIcon.setVisibility(View.VISIBLE);
             mVoice.setVisibility(View.GONE);
             mLable.setVisibility(View.VISIBLE);
@@ -53,8 +56,9 @@ public class DialogManager {
             mLable.setText("松开手指 取消发送");
         }
     }
-    public void tooShort(){
-        if (mDialog!=null && mDialog.isShowing()){
+
+    public void tooShort() {
+        if (mDialog != null && mDialog.isShowing()) {
             mIcon.setVisibility(View.VISIBLE);
             mVoice.setVisibility(View.GONE);
             mLable.setVisibility(View.VISIBLE);
@@ -63,20 +67,22 @@ public class DialogManager {
             mLable.setText("录音时间过短");
         }
     }
-    public void dimissDialog(){
-        if (mDialog!=null && mDialog.isShowing()){
+
+    public void dimissDialog() {
+        if (mDialog != null && mDialog.isShowing()) {
             mDialog.dismiss();
             mDialog = null;
         }
     }
+
     //level 1-7
-    public void updateVoiceLevel(int level){
-        if (mDialog!=null && mDialog.isShowing()){
+    public void updateVoiceLevel(int level) {
+        if (mDialog != null && mDialog.isShowing()) {
 //            mIcon.setVisibility(View.VISIBLE);
 //            mVoice.setVisibility(View.VISIBLE);
 //            mLable.setVisibility(View.VISIBLE);
 
-            int resId = mContext.getResources().getIdentifier("v"+level,"mipmap",mContext.getPackageName());
+            int resId = mContext.getResources().getIdentifier("v" + level, "mipmap", mContext.getPackageName());
             mVoice.setImageResource(resId);
         }
     }
diff --git a/app/src/main/java/cc/minsnail/manager/MediaManager.java b/app/src/main/java/cc/minsnail/manager/MediaManager.java
deleted file mode 100644 (file)
index 04e45c5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-package cc.minsnail.manager;
-
-import android.media.*;
-import android.media.AudioManager;
-
-import java.io.IOException;
-
-/**
- * Created by yg on 2016/10/25.
- */
-public class MediaManager {
-    private static MediaPlayer mMediaPlayer;
-    private static boolean isPause;
-
-    public static void playSound(String filePath, MediaPlayer.OnCompletionListener listener){
-        if (mMediaPlayer == null){
-            mMediaPlayer = new MediaPlayer();
-            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
-                @Override
-                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
-                    mMediaPlayer.reset();
-                    return false;
-                }
-            });
-        }else {
-            mMediaPlayer.reset();
-        }
-        try {
-            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-            mMediaPlayer.setOnCompletionListener(listener);
-            mMediaPlayer.setDataSource(filePath);
-            mMediaPlayer.prepare();
-            mMediaPlayer.start();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-    public static void pause(){
-        if (mMediaPlayer != null&&mMediaPlayer.isPlaying()){
-            mMediaPlayer.pause();
-            isPause = true;
-        }
-    }
-    public static void resume(){
-        if (mMediaPlayer != null&& isPause){
-            mMediaPlayer.start();
-            isPause = false;
-        }
-    }
-    public static void release(){
-        if (mMediaPlayer != null){
-            mMediaPlayer.release();
-            mMediaPlayer = null;
-        }
-    }
-}
diff --git a/app/src/main/java/cc/minsnail/manager/MediaPlayerManager.java b/app/src/main/java/cc/minsnail/manager/MediaPlayerManager.java
new file mode 100644 (file)
index 0000000..6390bce
--- /dev/null
@@ -0,0 +1,127 @@
+package cc.minsnail.manager;
+
+import android.media.*;
+import android.media.AudioManager;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.io.IOException;
+
+import cc.minsnail.view.ChatSurfaceView;
+
+/**
+ * Created by yg on 2016/10/25.
+ */
+public class MediaPlayerManager implements MediaPlayer.OnPreparedListener,SurfaceHolder.Callback{
+    private static MediaPlayerManager mInstance;
+    private static MediaPlayer mMediaPlayer;
+    private SurfaceHolder mHolder;
+    private boolean isPause;
+    private boolean isPrepare;
+    private MediaPlayerManager(){}
+    public static MediaPlayerManager getInstance(){
+        if (mInstance == null){
+            synchronized (MediaPlayerManager.class){
+                if (mInstance == null){
+                    mInstance = new MediaPlayerManager();
+                }
+            }
+        }
+        return mInstance;
+    }
+    private void resetMediaPlayer(){
+        if (mMediaPlayer == null) {
+            mMediaPlayer = new MediaPlayer();
+            mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
+                    mMediaPlayer.reset();
+                    return false;
+                }
+            });
+        } else {
+            mMediaPlayer.reset();
+        }
+    }
+    public void playAudio(String filePath, MediaPlayer.OnCompletionListener listener) {
+        resetMediaPlayer();
+        try {
+            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mMediaPlayer.setOnCompletionListener(listener);
+            mMediaPlayer.setDataSource(filePath);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+    public void playVideo(ChatSurfaceView surfaceView, String path, MediaPlayer.OnCompletionListener onCompletionListener){
+        resetMediaPlayer();
+        mHolder = surfaceView.getHolder();
+        //mHolder.addCallback(this);
+        Log.i("MediaPlayer",path);
+        try {
+            mMediaPlayer.setDisplay(mHolder);
+            mMediaPlayer.setOnCompletionListener(onCompletionListener);
+            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mMediaPlayer.setDataSource(path);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+        }catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+    public void playVideo(SurfaceHolder holder,String path){
+        resetMediaPlayer();
+        try {
+            mMediaPlayer.setDisplay(holder);
+            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mMediaPlayer.setDataSource(path);
+            mMediaPlayer.prepare();
+            mMediaPlayer.start();
+        }catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+    public void pause() {
+        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+            mMediaPlayer.pause();
+            isPause = true;
+        }
+    }
+
+    public void resume() {
+        if (mMediaPlayer != null && isPause) {
+            mMediaPlayer.start();
+            isPause = false;
+        }
+    }
+
+    public void release() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+        }
+    }
+
+    @Override
+    public void onPrepared(MediaPlayer mediaPlayer) {
+        mediaPlayer.start();
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder surfaceHolder) {
+        mMediaPlayer.setDisplay(surfaceHolder);
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
+
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
+
+    }
+}
index e8bd3b7..1278e0e 100644 (file)
@@ -28,7 +28,7 @@ public class OssManager {
         mConfig = new ClientConfiguration();
         //config.setConnectionTimeout(15*1000);
 
-        oss = new OSSClient(context, "http://"+Config.OSS_ENDPOINT, mCredentialProvider, mConfig);
+        oss = new OSSClient(context, "http://" + Config.OSS_ENDPOINT, mCredentialProvider, mConfig);
     }
 
     public static OssManager getInstance(Context context) {
@@ -40,8 +40,8 @@ public class OssManager {
         return mOssManager;
     }
 
-    public String imageObjectKey(String objectKey){
-        String bb = "http://"+Config.OSS_BUCKET_NAME+"."+Config.OSS_ENDPOINT;
+    public String imageObjectKey(String objectKey) {
+        String bb = "http://" + Config.OSS_BUCKET_NAME + "." + Config.OSS_ENDPOINT;
         return null;
     }
 
index 98a0f95..e9f051f 100644 (file)
@@ -8,11 +8,16 @@ import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
 import android.util.Log;
 
+import cc.minsnail.Contents;
 import cc.minsnail.activity.ChatActivity;
+import cc.minsnail.beans.MainMessageItem;
 import cc.minsnail.beans.YgMessage;
 import cc.minsnail.config.Config;
+import cc.minsnail.service.ClientService;
 import cc.minsnail.smackclient.R;
 
 /**
@@ -23,12 +28,12 @@ public class MsgReceiver extends BroadcastReceiver {
 
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     @Override
-    public void onReceive(Context context, Intent intent) {
+    public void onReceive(final Context context, Intent intent) {
         if (intent.getAction().equals(TAG)) {
             Log.i(TAG, "received message");
-            YgMessage ygMessage = intent.getParcelableExtra("msg");
-            NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
-            Notification.Builder builder = new Notification.Builder(context);
+            final YgMessage ygMessage = intent.getParcelableExtra("msg");
+            final NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
+            final Notification.Builder builder = new Notification.Builder(context);
             Intent i = new Intent(context, ChatActivity.class);
             i.putExtra(Config.KEY_FROM_JID, ygMessage.getFrom());
             i.putExtra(Config.KEY_FROM_NAME, ygMessage.getFrom().split("@")[0]);
@@ -41,8 +46,25 @@ public class MsgReceiver extends BroadcastReceiver {
                     .setWhen(System.currentTimeMillis())
                     .setAutoCancel(true);
             builder.setContentIntent(pi);
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    ossLoadImage(context, ygMessage);
+                }
+            }).start();
             notificationManager.notify((int) (Math.random() * 100), builder.build());
             abortBroadcast();
         }
     }
+
+    private void ossLoadImage(Context context, YgMessage ygMessage) {
+        MainMessageItem item = new MainMessageItem(ygMessage);
+        if (item.getType() == Contents.CHAT_TYPE_IMAGE_L_INT) {
+            Intent intent = new Intent(context, ClientService.class);
+            intent.setAction(Config.CLIENT_SERVER_ACTION_DOWNLOAD_PIC);
+            intent.putExtra(Config.KEY_MESSAGE_PIC, (Parcelable) item);
+
+            context.startService(intent);
+        }
+    }
 }
index 5e7a51d..ee01437 100644 (file)
@@ -2,13 +2,39 @@ package cc.minsnail.service;
 
 import android.app.Service;
 import android.content.Intent;
+import android.os.Environment;
 import android.os.IBinder;
 import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.alibaba.sdk.android.oss.ClientException;
+import com.alibaba.sdk.android.oss.ServiceException;
+import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
+import com.alibaba.sdk.android.oss.model.GetObjectRequest;
+import com.alibaba.sdk.android.oss.model.GetObjectResult;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import cc.minsnail.Contents;
+import cc.minsnail.activity.ChatActivity;
+import cc.minsnail.beans.ChatMessageItem;
+import cc.minsnail.config.Config;
+import cc.minsnail.database.DataBaseManager;
+import cc.minsnail.manager.OssManager;
 
 /**
  * Created by yg on 2016/10/25.
  */
 public class ClientService extends Service {
+    private OssManager mOssManger;
+    private DataBaseManager mDataBaseManger;
+    private File picPath;
+
     @Nullable
     @Override
     public IBinder onBind(Intent intent) {
@@ -18,10 +44,70 @@ public class ClientService extends Service {
     @Override
     public void onCreate() {
         super.onCreate();
+        mOssManger = OssManager.getInstance(ClientService.this);
+        mDataBaseManger = DataBaseManager.getInstance(ClientService.this);
+        picPath = new File(new File(Environment.getExternalStorageDirectory(), Config.APP_PATH), Config.PIC_PATH);
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
+        switch (intent.getAction()) {
+            case Config.CLIENT_SERVER_ACTION_DOWNLOAD_PIC:
+                downloadPic(intent);
+                break;
+        }
+
         return super.onStartCommand(intent, flags, startId);
     }
+
+    private void downloadPic(Intent intent) {
+        final ChatMessageItem item = intent.getParcelableExtra(Config.KEY_MESSAGE_PIC);
+        if (item.getType() == Contents.CHAT_TYPE_IMAGE_L_INT) {
+            String fileName = item.getText();
+            if (!picPath.exists()) picPath.mkdirs();
+            String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
+            final File file = new File(picPath, System.currentTimeMillis() + ext);
+            GetObjectRequest get = new GetObjectRequest(Config.OSS_BUCKET_NAME, fileName);
+            mOssManger.oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
+                @Override
+                public void onSuccess(GetObjectRequest getObjectRequest, GetObjectResult getObjectResult) {
+                    InputStream inputStream = getObjectResult.getObjectContent();
+                    try {
+                        OutputStream outputStream = new FileOutputStream(file);
+                        byte[] buffer = new byte[1024];
+                        int len;
+                        while ((len = inputStream.read(buffer)) != -1) {
+                            outputStream.write(buffer, 0, len);
+                        }
+                        outputStream.flush();
+                        outputStream.close();
+                        inputStream.close();
+                        item.setText(file.getAbsolutePath());
+                        mDataBaseManger.insertChatMessageItem(item);
+                        mDataBaseManger.updateMainMessageItem(item);
+                    } catch (FileNotFoundException e) {
+                        e.printStackTrace();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                @Override
+                public void onFailure(GetObjectRequest getObjectRequest, ClientException e, ServiceException e1) {
+                    // 请求异常
+                    if (e != null) {
+                        // 本地异常如网络异常等
+                        e.printStackTrace();
+                    }
+                    if (e1 != null) {
+                        // 服务异常
+                        Log.e("ErrorCode", e1.getErrorCode());
+                        Log.e("RequestId", e1.getRequestId());
+                        Log.e("HostId", e1.getHostId());
+                        Log.e("RawMessage", e1.getRawMessage());
+                    }
+                }
+            });
+        }
+    }
 }
index 5fddce4..0c52962 100644 (file)
@@ -80,6 +80,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import cc.minsnail.beans.MainMessageItem;
 import cc.minsnail.config.Config;
 import cc.minsnail.beans.YgInfo;
 import cc.minsnail.beans.YgMessage;
@@ -331,7 +332,7 @@ public class SmackService extends Service {
         } catch (XMPPException e) {
             e.printStackTrace();
             XMPPError error = e.getXMPPError();
-            if(error!=null){
+            if (error != null) {
                 switch (error.getCode()) {
                     case 502:
                         Log.e(TAG, "无法连接远程服务器");
@@ -473,14 +474,19 @@ public class SmackService extends Service {
                 info.setBody("Server not connected");
             }
         } catch (XMPPException e) {
-            e.printStackTrace();
-            XMPPError error = e.getXMPPError();
-            if (error != null) {
-                info.setCode(error.getCode());
-                info.setBody(error.getMessage());
+            if (e != null) {
+                XMPPError error = e.getXMPPError();
+                if (error != null) {
+                    info.setCode(error.getCode());
+                    info.setBody(error.getMessage());
+                } else {
+                    info.setCode(400);
+                    info.setBody("No response from the server");
+                }
+                e.printStackTrace();
             } else {
                 info.setCode(400);
-                info.setBody("No response from the server");
+                info.setBody(" not-authorized(401)");
             }
         }
         return info;
@@ -852,8 +858,7 @@ public class SmackService extends Service {
     private YgInfo _addFriend(String user, String name, String[] groups) {
         YgInfo info = new YgInfo();
         try {
-            roster.createGroup("yhhy");
-            roster.createEntry(checkUser(user), name, new String[]{"yhhy"});
+            roster.createEntry(checkUser(user), name, groups);
             info.setCode(200);
             info.setBody("add " + user + "success");
             Log.i(TAG, "添加" + user + "好友成功");
@@ -899,19 +904,7 @@ public class SmackService extends Service {
 
     private void testMethod() {
         Log.i(TAG, "testMethod");
-        //createGroup();
-        getGroups();
-        //Log.i(TAG,roster.getGroupCount()+"");
-        //roster.createGroup("hdu");
-//        RosterGroup rosterGroup = roster.getGroup("yhhy");
-//        Collection<RosterEntry> rosterEntries = rosterGroup.getEntries();
-//        for (RosterEntry entry:rosterEntries){
-//            Log.i(TAG,entry.getName());
-//        }
-        Log.i(TAG, "stop test");
-        //_sendIQ();
-        //Log.i(TAG,roster.getEntry("zj@1546e5j729.imwork.net/Smack")!=null?"true":"false");
-        //Log.i(TAG,roster.getEntry("zj")!=null?"true":"false");
+
     }
 
     private MessageListener getMessageListener() {
@@ -992,7 +985,7 @@ public class SmackService extends Service {
         }
 
         public YgInfo sendChatMessage(String toUser, YgMessage ygMessage) {
-            YgInfo ygInfo = new YgInfo();
+            YgInfo ygInfo;
             Message message = new Message();
             message.setTo(ygMessage.getTo());
             message.setFrom(ygMessage.getFrom());
index be70b66..ff7142b 100644 (file)
@@ -3,26 +3,39 @@ package cc.minsnail.tools;
 import android.content.Context;
 import android.content.SharedPreferences;
 
+import cc.minsnail.config.Config;
+
 /**
  * Created by yg on 2016/10/31.
  */
 public class SharedHelper {
-    private static final String preference_file_key = "cc.minsnail.smackclient.SHARED_MY";
     private Context mContext;
+    private static SharedHelper mInstance;
 
-    public SharedHelper(Context context) {
+    private SharedHelper(Context context) {
         mContext = context;
     }
 
+    public static SharedHelper getInstance(Context context) {
+        if (mInstance == null) {
+            synchronized (SharedHelper.class) {
+                if (mInstance == null) {
+                    mInstance = new SharedHelper(context);
+                }
+            }
+        }
+        return mInstance;
+    }
+
     public void put(String key, String value) {
-        SharedPreferences preferences = mContext.getSharedPreferences(preference_file_key, mContext.MODE_PRIVATE);
+        SharedPreferences preferences = mContext.getSharedPreferences(Config.SHARED_PREFERENCE_FILE_KEY, mContext.MODE_PRIVATE);
         SharedPreferences.Editor editor = preferences.edit();
         editor.putString(key, value);
         editor.commit();
     }
 
     public String get(String key, String defaultValue) {
-        SharedPreferences preferences = mContext.getSharedPreferences(preference_file_key, mContext.MODE_PRIVATE);
+        SharedPreferences preferences = mContext.getSharedPreferences(Config.SHARED_PREFERENCE_FILE_KEY, mContext.MODE_PRIVATE);
         return preferences.getString(key, defaultValue);
     }
 }
index 3cc694c..e41a351 100644 (file)
@@ -16,7 +16,7 @@ import cc.minsnail.beans.YgUserNode;
 public class TreeHelper {
     public static <T> List<YgTreeNode> toNode(List<YgUserNode> datas) throws IllegalAccessException {
         List<YgTreeNode> nodes = new ArrayList<>();
-        for (YgUserNode t:datas){
+        for (YgUserNode t : datas) {
             YgTreeNode node = new YgTreeNode();
             node.setId(t.getId());
             node.setPid(t.getPid());
@@ -42,14 +42,14 @@ public class TreeHelper {
             nodes.add(node);
         }
         //确定父节点叶子节点关系
-        for (int i=0;i<nodes.size();i++){
+        for (int i = 0; i < nodes.size(); i++) {
             YgTreeNode node1 = nodes.get(i);
-            for (int j = i + 1; j < nodes.size();j++){
+            for (int j = i + 1; j < nodes.size(); j++) {
                 YgTreeNode node2 = nodes.get(j);
-                if (node2.getPid() == node1.getId()){
+                if (node2.getPid() == node1.getId()) {
                     node1.getChildren().add(node2);
                     node2.setParent(node1);
-                } else if (node1.getPid() == node2.getId()){
+                } else if (node1.getPid() == node2.getId()) {
                     node2.getChildren().add(node1);
                     node1.setParent(node2);
                 }
@@ -57,39 +57,43 @@ public class TreeHelper {
         }
         return nodes;
     }
-    public static <T> List<YgTreeNode> getSortedNodes(List<YgUserNode> datas,int defaultExpandLevel) throws IllegalAccessException {
+
+    public static <T> List<YgTreeNode> getSortedNodes(List<YgUserNode> datas, int defaultExpandLevel) throws IllegalAccessException {
         List<YgTreeNode> result = new ArrayList<>();
         List<YgTreeNode> nodes = toNode(datas);
         List<YgTreeNode> rootNodes = getRootNodes(nodes);
-        for (YgTreeNode node:rootNodes){
-            addNode(result,node,defaultExpandLevel,1);
+        for (YgTreeNode node : rootNodes) {
+            addNode(result, node, defaultExpandLevel, 1);
         }
         return result;
     }
-    public static List<YgTreeNode> filterVisibleNodes(List<YgTreeNode> nodes){
+
+    public static List<YgTreeNode> filterVisibleNodes(List<YgTreeNode> nodes) {
         List<YgTreeNode> result = new ArrayList<>();
-        for (YgTreeNode node:nodes){
-            if (node.isRoot()||node.isParentExpand()){
+        for (YgTreeNode node : nodes) {
+            if (node.isRoot() || node.isParentExpand()) {
                 // TODO: 2016/10/28
                 result.add(node);
             }
         }
         return result;
     }
+
     private static void addNode(List<YgTreeNode> result, YgTreeNode node, int defaultExpandLevel, int currentLevel) {
         result.add(node);
-        if (defaultExpandLevel >= currentLevel){
+        if (defaultExpandLevel >= currentLevel) {
             node.setExpand(true);
         }
         if (node.isLeaf()) return;
-        for (int i= 0;i<node.getChildren().size();i++){
-            addNode(result,node.getChildren().get(i),defaultExpandLevel,currentLevel+1);
+        for (int i = 0; i < node.getChildren().size(); i++) {
+            addNode(result, node.getChildren().get(i), defaultExpandLevel, currentLevel + 1);
         }
     }
+
     private static List<YgTreeNode> getRootNodes(List<YgTreeNode> nodes) {
         List<YgTreeNode> rootNodes = new ArrayList<>();
-        for (YgTreeNode node:nodes){
-            if (node.isRoot()){
+        for (YgTreeNode node : nodes) {
+            if (node.isRoot()) {
                 rootNodes.add(node);
             }
         }
index 6f52ee7..c172dd2 100644 (file)
@@ -4,6 +4,8 @@ package cc.minsnail.tools;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.Environment;
+import android.util.Log;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -15,7 +17,10 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
+import cc.minsnail.Contents;
 import cc.minsnail.config.Config;
 
 /**
@@ -121,4 +126,48 @@ public class Utils {
         }
         return BitmapFactory.decodeByteArray(baos.toByteArray(), 0, 1);
     }
+
+    /** Create a file Uri for saving an image or video */
+    public static Uri getOutputMediaFileUri(File file){
+        return Uri.fromFile(file);
+    }
+
+    /** Create a File for saving an image or video */
+    public static File getOutputMediaFile(int type){
+        // To be safe, you should check that the SDCard is mounted
+        // using Environment.getExternalStorageState() before doing this.
+        File root = new File(Environment.getExternalStorageDirectory(), Config.APP_PATH);
+        File mediaStorageDir = null;
+        switch (type){
+            case Contents.MEDIA_TYPE_AUDIO:
+                mediaStorageDir = new File(root,Config.AUDIO_PATH);
+                break;
+            case Contents.MEDIA_TYPE_VIDEO:
+                mediaStorageDir = new File(root,Config.VIDEO_PATH);
+                break;
+        }
+        if (mediaStorageDir == null) return null;
+        // This location works best if you want the created images to be shared
+        // between applications and persist after your app has been uninstalled.
+
+        // Create the storage directory if it does not exist
+        if (!mediaStorageDir.exists()){
+            mediaStorageDir.mkdirs();
+        }
+
+        // Create a media file name
+        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+        File mediaFile;
+        if (type == Contents.MEDIA_TYPE_AUDIO){
+            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
+                    "AUD_"+ timeStamp + ".arm");
+        } else if(type == Contents.MEDIA_TYPE_VIDEO) {
+            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
+                    "VID_"+ timeStamp + ".mp4");
+        } else {
+            return null;
+        }
+
+        return mediaFile;
+    }
 }
index 1733b03..36be0ad 100644 (file)
@@ -10,14 +10,14 @@ import android.view.View;
 import android.widget.Button;
 
 import cc.minsnail.config.Config;
-import cc.minsnail.manager.AudioManager;
+import cc.minsnail.manager.AudioRecorderManager;
 import cc.minsnail.manager.DialogManager;
 import cc.minsnail.smackclient.R;
 
 /**
  * Created by yg on 2016/10/24.
  */
-public class AudioRecordeButton extends Button implements AudioManager.AudioStateListener {
+public class AudioRecordeButton extends Button implements AudioRecorderManager.AudioStateListener {
     private static final int DISTANCE_Y_CANCEL = 50;
     private static final int DISTANCE_X_CANCEL = 10;
     private static final int STATE_NORMAL = 1;
@@ -27,7 +27,7 @@ public class AudioRecordeButton extends Button implements AudioManager.AudioStat
     private boolean isRecording = false;
 
     private DialogManager mDialogManager;
-    private AudioManager mAudioManager;
+    private AudioRecorderManager mAudioRecorderManager;
 
     private float mTime = 0;
     //是否触发 long click
@@ -41,14 +41,14 @@ public class AudioRecordeButton extends Button implements AudioManager.AudioStat
         super(context, attrs);
         mDialogManager = new DialogManager(getContext());
         String dir = Environment.getExternalStorageDirectory() + "/" + Config.APP_PATH + "/" + Config.AUDIO_PATH;
-        mAudioManager = AudioManager.getInstance(dir);
-        mAudioManager.setAudioStateListener(this);
+        mAudioRecorderManager = AudioRecorderManager.getInstance(dir);
+        mAudioRecorderManager.setAudioStateListener(this);
         setOnLongClickListener(new OnLongClickListener() {
             @Override
             public boolean onLongClick(View view) {
                 //// TODO: 2016/10/24
                 mReady = true;
-                mAudioManager.prepareAudio();
+                mAudioRecorderManager.prepareAudio();
                 return false;
             }
         });
@@ -93,7 +93,7 @@ public class AudioRecordeButton extends Button implements AudioManager.AudioStat
                     new Thread(mGetVoiceLevelRunnable).start();
                     break;
                 case MSG_VOICE_CHANGED:
-                    mDialogManager.updateVoiceLevel(mAudioManager.getVoiceLevel(7));
+                    mDialogManager.updateVoiceLevel(mAudioRecorderManager.getVoiceLevel(7));
                     break;
                 case MSG_DIALOG_DIMMIS:
                     mDialogManager.dimissDialog();
@@ -134,19 +134,19 @@ public class AudioRecordeButton extends Button implements AudioManager.AudioStat
                 }
                 if (!isRecording || mTime < 0.6f) {
                     mDialogManager.tooShort();
-                    mAudioManager.cancel();
+                    mAudioRecorderManager.cancel();
                     mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMMIS, 1300);
                 } else if (mCurState == STATE_RECORDING) {
                     //正常录制结束
                     // TODO: 2016/10/25
                     mDialogManager.dimissDialog();
-                    mAudioManager.release();
+                    mAudioRecorderManager.release();
                     if (mListener != null) {
-                        mListener.onFinish(mTime, mAudioManager.getCurrentFilePath());
+                        mListener.onFinish(mTime, mAudioRecorderManager.getCurrentAudioFilePath());
                     }
                 } else if (mCurState == STATE_WANT_CANCEL) {
                     mDialogManager.dimissDialog();
-                    mAudioManager.cancel();
+                    mAudioRecorderManager.cancel();
                 }
                 reset();
                 break;
index ffa2fe1..e65e8e6 100644 (file)
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:orientation="vertical">
     <!--toolBar-->
     <include layout="@layout/activity_chat_toolbar"></include>
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical" android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="#ebe7e7"
-    android:weightSum="1">
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#ebe7e7"
+        android:orientation="vertical">
+
         <ListView
-            android:layout_width="wrap_content"
-            android:layout_height="0dp"
-            android:layout_weight="1"
             android:id="@+id/chatbox"
-            android:dividerHeight="10dp"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_above="@+id/chat_bottom_bar"
+            android:layout_alignParentTop="true"
             android:background="#ebebeb"
             android:divider="@null"
-            android:paddingTop="10dp"/>
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="3px"
-        android:background="#ccc"></View>
+            android:dividerHeight="10dp"
+            android:transcriptMode="alwaysScroll" />
 
-    <RelativeLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="60dp"
-        android:background="#fff"
-        android:layout_gravity="center_horizontal">
-        <RelativeLayout
-            android:id="@+id/sendText"
-            android:visibility="visible"
+        <LinearLayout
+            android:id="@+id/chat_bottom_bar"
             android:layout_width="match_parent"
-            android:layout_height="60dp"
-            android:layout_toLeftOf="@+id/more"
-            android:layout_toStartOf="@+id/more">
-            <EditText
+            android:layout_height="70dp"
+            android:layout_alignParentBottom="true"
+            android:orientation="vertical">
+
+            <View
+                android:id="@+id/line1"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:inputType="textMultiLine"
-                android:ems="10"
-                android:id="@+id/content"
-                android:layout_marginTop="10dp"
-                android:layout_toLeftOf="@+id/send"
-                android:layout_toStartOf="@+id/send" />
-            <Button
-                android:layout_width="50dp"
-                android:layout_height="40dp"
-                android:text="发送"
-                android:id="@+id/send"
-                android:layout_gravity="right"
-                android:background="@drawable/button_background"
-                android:layout_alignTop="@+id/content"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentEnd="true"
-                style="?android:attr/borderlessButtonStyle"/>
-
-        </RelativeLayout>
-        <RelativeLayout
-            android:id="@+id/sendAudio"
-            android:visibility="gone"
-            android:layout_width="match_parent"
-            android:layout_height="60dp"
-            android:layout_toLeftOf="@+id/more"
-            android:layout_toStartOf="@+id/more">
-
-            <ImageButton
-                android:layout_width="40dp"
-                android:layout_height="40dp"
-                android:id="@+id/chanage"
-                android:background="@mipmap/chanage"
-                android:layout_centerVertical="true"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentStart="true" />
-
-            <cc.minsnail.view.AudioRecordeButton
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/str_recorder_normal"
-                android:textColor="#727272"
-                android:id="@+id/recorder_button"
-                android:layout_centerVertical="true"
-                android:layout_toRightOf="@+id/chanage"
-                android:background="@drawable/button_background"
-                android:layout_marginLeft="16dp"
-                android:layout_marginStart="16dp"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentEnd="true"
-                style="?android:attr/borderlessButtonStyle"/>
-        </RelativeLayout>
-
-        <ImageButton
-            android:layout_width="40dp"
-            android:layout_height="40dp"
-            android:id="@+id/more"
-            android:layout_marginRight="3dp"
-            android:background="@mipmap/more"
-            android:layout_centerVertical="true"
-            android:layout_alignParentRight="true"
-            android:layout_alignParentEnd="true" />
+                android:layout_height="3px"
+                android:background="#ccc"></View>
 
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+                android:layout_gravity="center_horizontal"
+                android:background="#fff"
+                android:orientation="horizontal">
+
+                <RelativeLayout
+                    android:id="@+id/sendText"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_toLeftOf="@+id/more"
+                    android:layout_toStartOf="@+id/more"
+                    android:visibility="visible">
+
+                    <EditText
+                        android:id="@+id/content"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="10dp"
+                        android:layout_toLeftOf="@+id/send"
+                        android:layout_toStartOf="@+id/send"
+                        android:ems="10"
+                        android:inputType="textMultiLine" />
+
+                    <Button
+                        android:id="@+id/send"
+                        style="?android:attr/borderlessButtonStyle"
+                        android:layout_width="50dp"
+                        android:layout_height="40dp"
+                        android:layout_alignParentEnd="true"
+                        android:layout_alignParentRight="true"
+                        android:layout_alignTop="@+id/content"
+                        android:layout_gravity="right"
+                        android:background="@drawable/button_background"
+                        android:text="发送" />
+
+                </RelativeLayout>
+
+                <RelativeLayout
+                    android:id="@+id/sendAudio"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_toLeftOf="@+id/more"
+                    android:layout_toStartOf="@+id/more"
+                    android:visibility="gone">
+
+                    <ImageButton
+                        android:id="@+id/chanage"
+                        android:layout_width="40dp"
+                        android:layout_height="40dp"
+                        android:layout_alignParentLeft="true"
+                        android:layout_alignParentStart="true"
+                        android:layout_centerVertical="true"
+                        android:background="@mipmap/chanage" />
+
+                    <cc.minsnail.view.AudioRecordeButton
+                        android:id="@+id/recorder_button"
+                        style="?android:attr/borderlessButtonStyle"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_alignParentEnd="true"
+                        android:layout_alignParentRight="true"
+                        android:layout_centerVertical="true"
+                        android:layout_marginLeft="16dp"
+                        android:layout_marginStart="16dp"
+                        android:layout_toRightOf="@+id/chanage"
+                        android:background="@drawable/button_background"
+                        android:text="@string/str_recorder_normal"
+                        android:textColor="#727272" />
+                </RelativeLayout>
+
+                <ImageButton
+                    android:id="@+id/more"
+                    android:layout_width="40dp"
+                    android:layout_height="40dp"
+                    android:layout_alignParentEnd="true"
+                    android:layout_alignParentRight="true"
+                    android:layout_centerVertical="true"
+                    android:layout_marginRight="3dp"
+                    android:background="@mipmap/more" />
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:id="@+id/subMenus"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:visibility="visible">
+
+                <GridLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:background="#fff">
+
+                    <ImageButton
+                        android:id="@+id/submenu_pic_btn"
+                        android:layout_width="40dp"
+                        android:layout_height="40dp"
+                        android:layout_column="0"
+                        android:layout_margin="10dp"
+                        android:layout_row="0"
+                        android:background="@drawable/picture" />
+
+                    <ImageButton
+                        android:id="@+id/submenu_audio_btn"
+                        android:layout_width="40dp"
+                        android:layout_height="40dp"
+                        android:layout_column="1"
+                        android:layout_margin="10dp"
+                        android:layout_row="0"
+                        android:background="@drawable/microphone" />
+
+                    <ImageButton
+                        android:id="@+id/submenu_video_btn"
+                        android:layout_width="40dp"
+                        android:layout_height="40dp"
+                        android:layout_column="2"
+                        android:layout_margin="10dp"
+                        android:layout_row="0"
+                        android:background="@mipmap/video_camera" />
+                </GridLayout>
+            </RelativeLayout>
+        </LinearLayout>
     </RelativeLayout>
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="3px"
-        android:background="#ccc"></View>
-    <RelativeLayout
-        android:id="@+id/subMenus"
-        android:layout_width="match_parent"
-        android:layout_height="100dp"
-        android:visibility="gone">
-        <GridLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:background="#fff">
-
-            <ImageButton
-                android:layout_width="40dp"
-                android:layout_height="40dp"
-                android:id="@+id/sendPic"
-                android:layout_margin="10dp"
-                android:layout_row="0"
-                android:layout_column="0"
-                android:background="@drawable/picture"/>
-
-            <ImageButton
-                android:layout_width="40dp"
-                android:layout_height="40dp"
-                android:id="@+id/audio"
-                android:layout_margin="10dp"
-                android:layout_row="0"
-                android:background="@drawable/microphone"
-                android:layout_column="1" />
-        </GridLayout>
-    </RelativeLayout>
-</LinearLayout>
 </LinearLayout>
\ No newline at end of file
index dc96de3..7e46afc 100644 (file)
@@ -1,24 +1,41 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal" android:layout_width="match_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingTop="5dp"
-    android:paddingBottom="5dp">
+    android:orientation="horizontal"
+    android:paddingBottom="5dp"
+    android:paddingTop="5dp">
+
     <ImageView
+        android:id="@+id/head"
         android:layout_width="60dp"
         android:layout_height="60dp"
-        android:id="@+id/head"
-        android:src="@mipmap/head"
-        android:layout_alignParentTop="true" />
-    <cc.minsnail.view.ChatImageView
-        android:layout_width="150sp"
-        android:layout_height="120sp"
-        android:id="@+id/pic"
-        android:src="@mipmap/head"
+        android:layout_alignParentTop="true"
+        android:src="@mipmap/head" />
+
+    <RelativeLayout
+        android:id="@+id/relativeLayout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
         android:layout_marginLeft="5dp"
         android:layout_marginStart="5dp"
-        android:layout_alignParentTop="true"
-        android:layout_toRightOf="@+id/head"
-        android:layout_toEndOf="@+id/head" />
+        android:layout_toEndOf="@+id/head"
+        android:layout_toRightOf="@+id/head">
+
+        <cc.minsnail.view.ChatImageView
+            android:id="@+id/pic"
+            android:layout_width="150sp"
+            android:layout_height="120sp"
+            android:src="@mipmap/head" />
+
+        <ProgressBar
+            android:id="@+id/image_progress_bar"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:visibility="gone" />
+    </RelativeLayout>
 
 </RelativeLayout>
\ No newline at end of file
index 1f880ff..a86653a 100644 (file)
@@ -1,24 +1,40 @@
 <?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal" android:layout_width="match_parent"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
-    android:paddingTop="5dp"
-    android:paddingBottom="5dp">
-    <cc.minsnail.view.ChatImageView
-        android:layout_width="150sp"
-        android:layout_height="120sp"
-        android:id="@+id/pic"
-        android:layout_marginRight="5dp"
-        android:layout_marginEnd="5dp"
-        android:layout_alignTop="@+id/head"
-        android:layout_toLeftOf="@+id/head"
-        android:src="@mipmap/head"/>
-    <ImageView
-        android:layout_width="60dp"
-        android:layout_height="60dp"
-        android:id="@+id/head"
-        android:src="@mipmap/head"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentEnd="true" />
-</RelativeLayout>
\ No newline at end of file
+    android:layout_width="match_parent">
+
+    <RelativeLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="5dp"
+        android:paddingBottom="5dp">
+        <cc.minsnail.view.ChatImageView
+            android:layout_width="150sp"
+            android:layout_height="120sp"
+            android:id="@+id/pic"
+            android:layout_marginRight="5dp"
+            android:layout_marginEnd="5dp"
+            android:layout_alignTop="@+id/head"
+            android:layout_toLeftOf="@+id/head"
+            android:src="@mipmap/head"/>
+        <ImageView
+            android:layout_width="60dp"
+            android:layout_height="60dp"
+            android:id="@+id/head"
+            android:src="@mipmap/head"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true" />
+
+        <ProgressBar
+            style="?android:attr/progressBarStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/image_progress_bar"
+            android:layout_centerVertical="true"
+            android:layout_toLeftOf="@+id/pic"
+            android:layout_toStartOf="@+id/pic"
+            android:visibility="gone"/>
+    </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
index ba6b725..eacb8e6 100644 (file)
@@ -37,5 +37,4 @@
         android:layout_alignParentTop="true"
         android:layout_alignParentRight="true"
         android:layout_alignParentEnd="true" />
-
 </RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_menu_back.png b/app/src/main/res/mipmap-hdpi/ic_menu_back.png
new file mode 100644 (file)
index 0000000..661a4ae
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_menu_back.png differ
diff --git a/app/src/main/res/mipmap-hdpi/video_camera.png b/app/src/main/res/mipmap-hdpi/video_camera.png
new file mode 100644 (file)
index 0000000..79600de
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/video_camera.png differ
diff --git a/app/src/main/res/mipmap-mdpi/video_camera.png b/app/src/main/res/mipmap-mdpi/video_camera.png
new file mode 100644 (file)
index 0000000..432e128
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/video_camera.png differ
index d3ca7f4..0fe57d2 100644 (file)
     <string name="str_login_out_dialog_message">退出登录?</string>
     <string name="str_ok">确定</string>
     <string name="str_cancel">取消</string>
+
+    <string name="str_message_audio_tag">[语音]</string>
+    <string name="str_message_image_tag">[图片]</string>
+    <string name="str_message_video_tag">[视频]</string>
     
     
     <item type="id" name="TAG_IMAGE_FILE_PATH"></item>