package com.arrownock.opensource.arrownockers.chat;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.arrownock.opensource.arrownockers.R;
import com.arrownock.opensource.arrownockers.chat.ChatMsgEntity.EntityType;
import com.arrownock.opensource.arrownockers.utils.AnUtils;
import com.arrownock.opensource.arrownockers.utils.AnIMWrapper;
import com.arrownock.opensource.arrownockers.utils.DBManager;
import com.arrownock.opensource.arrownockers.utils.DBManager.Chat;
import com.arrownock.opensource.arrownockers.utils.MapActivity;
import com.arrownock.opensource.arrownockers.utils.MapCallback;
import com.arrownock.opensource.arrownockers.utils.MapCallback.OnLocationUpdated;
import com.baidu.location.BDLocation;
public class ChatActivity extends Activity implements OnClickListener,
OnLongClickListener, OnTouchListener, OnLocationUpdated {
private Button mBtnSend;
private Button mBtnImage;
private Button mBtnAudio;
private EditText mEditTextContent;
private TextView tvTitle;
private RelativeLayout rlBottom;
private RelativeLayout rlMore;
private ListView mListView;
private ChatMsgViewAdapter mAdapter;
private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>();
private List<String> clientIdsList;
private List<String> allClientIds;
MediaRecorder recorder;
boolean recording = false;
ProgressBar pBar;
public boolean alive = false;
private boolean willSendLocation = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_list);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
recorder = null;
Bundle bundle = new Bundle();
bundle = this.getIntent().getExtras();
setClientIds(bundle.getString("clientIds"));
tvTitle = (TextView) findViewById(R.id.tv_title);
tvTitle.setText(bundle.getString("realnames"));
initView();
initData();
AnIMWrapper.chatActivity = this;
MapCallback.setChatActivity(this);
alive = true;
}
@Override
protected void onRestart() {
super.onRestart();
alive = true;
initData();
}
@Override
protected void onDestroy() {
super.onDestroy();
alive = false;
AnIMWrapper.chatActivity = null;
MapCallback.setChatActivity(null);
}
@Override
protected void onStop() {
super.onStop();
alive = false;
}
public void addNewLocation(boolean income, double lat, double lon) {
ChatMsgEntity entity = new ChatMsgEntity();
entity.date = AnUtils.getTimeString(new Date());
if (income) {
entity.realname = "";
} else {
entity.realname = AnUtils.getCurrentRealname();
}
entity.isComMsg = income;
entity.entityType = EntityType.ET_LOCATION;
entity.text = "Location...";
entity.latitude = lat;
entity.longitude = lon;
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
if (!income) {
mEditTextContent.setText("");
}
mListView.setSelection(mListView.getCount() - 1);
}
public void addNewMessage(boolean income, String message) {
ChatMsgEntity entity = new ChatMsgEntity();
entity.date = AnUtils.getTimeString(new Date());
if (income) {
entity.realname = "";
} else {
entity.realname = AnUtils.getCurrentRealname();
}
entity.isComMsg = income;
entity.entityType = EntityType.ET_TEXT;
entity.text = message;
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
if (!income) {
mEditTextContent.setText("");
}
mListView.setSelection(mListView.getCount() - 1);
}
public void addNewImage(boolean income, byte[] bytes) {
ChatMsgEntity entity = new ChatMsgEntity();
entity.date = AnUtils.getTimeString(new Date());
if (income) {
entity.realname = "";
} else {
entity.realname = AnUtils.getCurrentRealname();
}
entity.isComMsg = income;
entity.entityType = EntityType.ET_IMAGE;
entity.imageBytes = bytes;
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getCount() - 1);
}
public void addNewAudio(boolean income, byte[] bytes) {
ChatMsgEntity entity = new ChatMsgEntity();
entity.date = AnUtils.getTimeString(new Date());
if (income) {
entity.realname = "";
} else {
entity.realname = AnUtils.getCurrentRealname();
}
entity.isComMsg = income;
entity.entityType = EntityType.ET_AUDIO;
entity.audioBytes = bytes;
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getCount() - 1);
if (income) {
playAudio(bytes);
}
}
@SuppressWarnings("resource")
public void playAudio(byte[] bytes) {
String pathString = Environment.getExternalStorageDirectory().getPath()
+ "/receivedAudio.m4a";
try {
File file = new File(pathString);
if (!file.exists()) {
file.createNewFile();
} else {
file.delete();
}
FileOutputStream os;
os = new FileOutputStream(file, false);
os.write(bytes);
os.close();
MediaPlayer mp = new MediaPlayer();
MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
};
mp.setOnCompletionListener(listener);
FileInputStream fis = new FileInputStream(pathString);
mp.setDataSource(fis.getFD());
mp.prepare();
Log.i("MediaPlayer", "Start Player");
mp.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startRecording() {
if (recording == true)
return;
if (recorder == null) {
String pathString = Environment.getExternalStorageDirectory()
.getPath() + "/recordedAudio.m4a";
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setOutputFile(pathString);
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
recorder.start();
} catch (Exception e) {
e.printStackTrace();
}
recording = true;
}
public void stopRecording() {
if (!recording) {
return;
}
String pathString = Environment.getExternalStorageDirectory().getPath()
+ "/recordedAudio.m4a";
File file = new File(pathString);
FileInputStream iStream;
try {
recorder.stop();
recording = false;
recorder.reset();
recorder.release();
recorder = null;
iStream = new FileInputStream(file);
sendAudio(IOUtils.toByteArray(iStream));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void initView() {
mListView = (ListView) findViewById(R.id.listview);
mBtnSend = (Button) findViewById(R.id.btn_send);
mBtnSend.setOnClickListener(this);
mBtnImage = (Button) findViewById(R.id.btn_sendImage);
mBtnImage.setOnClickListener(this);
mBtnAudio = (Button) findViewById(R.id.btn_sendAudio);
mBtnAudio.setOnLongClickListener(this);
mBtnAudio.setOnTouchListener(this);
pBar = (ProgressBar) findViewById(R.id.progressBar);
rlBottom = (RelativeLayout) findViewById(R.id.rl_bottom);
rlMore = (RelativeLayout) findViewById(R.id.rl_more);
mEditTextContent = (EditText) findViewById(R.id.et_sendmessage);
mAdapter = new ChatMsgViewAdapter(this, mDataArrays);
mListView.setAdapter(mAdapter);
}
public void initData() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
allClientIds = new ArrayList<String>(clientIdsList);
allClientIds.add(AnUtils.getCurrentClientId());
Collections.sort(allClientIds);
List<Chat> chatList = DBManager.getAllChats(
StringUtils.join(allClientIds, ","), "parties");
if (chatList == null) {
return;
}
mDataArrays.clear();
for (Chat chat : chatList) {
ChatMsgEntity chatMsgEntity = new ChatMsgEntity();
chatMsgEntity.realname = chat.realname;
chatMsgEntity.messageId = chat.messageId;
chatMsgEntity.date = chat.time;
chatMsgEntity.isComMsg = chat.income;
chatMsgEntity.status = chat.status;
String dataType = chat.type;
if (dataType.equals("image")) {
chatMsgEntity.entityType = EntityType.ET_IMAGE;
chatMsgEntity.imageBytes = chat.binary;
} else if (dataType.equals("audio")) {
chatMsgEntity.entityType = EntityType.ET_AUDIO;
chatMsgEntity.audioBytes = chat.binary;
} else if (dataType.equals("text")) {
chatMsgEntity.entityType = EntityType.ET_TEXT;
chatMsgEntity.text = chat.message;
} else if (dataType.equals("location")) {
chatMsgEntity.entityType = EntityType.ET_LOCATION;
chatMsgEntity.text = chat.message;
chatMsgEntity.latitude = chat.latitude;
chatMsgEntity.longitude = chat.longitude;
}
mDataArrays.add(chatMsgEntity);
}
runOnUiThread(new Runnable() {
public void run() {
mAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getCount() - 1);
}
});
for (Chat chat : chatList) {
if (chat.status.equals("unread") && chat.income) {
AnIMWrapper.getWrapper().sendReadACKToClients(
clientIdsList, chat.messageId);
DBManager
.updateChatStatus(chat.messageId, true, "read");
}
}
DBManager.setSessionRead(clientIdsList);
}
});
thread.start();
}
public void refresh() {
List<Chat> chatList = DBManager.getAllChats(
StringUtils.join(allClientIds, ","), "parties");
if (chatList == null) {
return;
}
mDataArrays.clear();
for (Chat chat : chatList) {
ChatMsgEntity chatMsgEntity = new ChatMsgEntity();
chatMsgEntity.realname = chat.realname;
chatMsgEntity.messageId = chat.messageId;
chatMsgEntity.date = chat.time;
chatMsgEntity.isComMsg = chat.income;
chatMsgEntity.status = chat.status;
String dataType = chat.type;
if (dataType.equals("image")) {
chatMsgEntity.entityType = EntityType.ET_IMAGE;
chatMsgEntity.imageBytes = chat.binary;
} else if (dataType.equals("audio")) {
chatMsgEntity.entityType = EntityType.ET_AUDIO;
chatMsgEntity.audioBytes = chat.binary;
} else if (dataType.equals("text")) {
chatMsgEntity.entityType = EntityType.ET_TEXT;
chatMsgEntity.text = chat.message;
} else if (dataType.equals("location")) {
chatMsgEntity.entityType = EntityType.ET_LOCATION;
chatMsgEntity.text = chat.message;
chatMsgEntity.latitude = chat.latitude;
chatMsgEntity.longitude = chat.longitude;
}
mDataArrays.add(chatMsgEntity);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getCount() - 1);
}
});
DBManager.setSessionRead(clientIdsList);
}
public void onChatSent(final String messageId) {
if (messageId != null) {
refresh();
} else {
AnUtils.showToast(ChatActivity.this, "发送失败请重试", Gravity.CENTER,
alive);
}
}
public void onChatReceived() {
refresh();
}
public void onChatRead() {
refresh();
}
public void onReceivedChat() {
refresh();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send:
sendText();
break;
case R.id.btn_sendImage:
ShowPickDialog();
break;
}
}
public void handleTap(final View view) {
ImageView iv = (ImageView) view;
ChatMsgEntity entity = (ChatMsgEntity) iv.getTag();
EntityType type = entity.entityType;
switch (type) {
case ET_AUDIO:
playAudio(entity.audioBytes);
break;
case ET_LOCATION:
showMap(entity.latitude, entity.longitude);
default:
break;
}
}
public void stopProgressBar() {
if (pBar != null) {
pBar.setVisibility(View.GONE);
}
}
public void showMore(View view) {
rlBottom.setVisibility(View.INVISIBLE);
rlBottom = (RelativeLayout) findViewById(R.id.rl_more);
rlBottom.setVisibility(View.VISIBLE);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(findViewById(R.id.et_sendmessage)
.getWindowToken(), 0);
}
public void showLess(View view) {
rlMore = (RelativeLayout) findViewById(R.id.rl_more);
rlMore.setVisibility(View.INVISIBLE);
rlMore = (RelativeLayout) findViewById(R.id.rl_bottom);
rlMore.setVisibility(View.VISIBLE);
}
public void showMap(double latitude, double longitude) {
Intent intent = new Intent(ChatActivity.this, MapActivity.class);
Bundle bundle = new Bundle();
bundle.putDouble("latitude", latitude);
bundle.putDouble("longitude", longitude);
intent.putExtras(bundle);
startActivity(intent);
}
public void sendLocation(View view) {
willSendLocation = true;
if (AnUtils.mapClient != null && AnUtils.mapClient.isStarted()) {
AnUtils.mapClient.requestLocation();
} else {
Toast.makeText(getBaseContext(), "位置服务模块未启动", Toast.LENGTH_LONG)
.show();
willSendLocation = false;
}
}
public void sendText() {
String contString = mEditTextContent.getText().toString();
if (contString.trim().length() > 0) {
AnIMWrapper.getWrapper().sendMessageToClients(contString,
clientIdsList);
addNewMessage(false, contString);
}
}
public void sendImage(byte[] bytes) {
addNewImage(false, bytes);
AnIMWrapper.getWrapper().sendBinaryToClients(bytes, "image",
clientIdsList);
}
public void sendAudio(byte[] bytes) {
addNewAudio(false, bytes);
AnIMWrapper.getWrapper().sendBinaryToClients(bytes, "audio",
clientIdsList);
}
public void sendLocation(double lat, double lon) {
addNewLocation(false, lat, lon);
AnIMWrapper.getWrapper().sendLocationToClients(lat, lon, clientIdsList);
}
private void ShowPickDialog() {
new AlertDialog.Builder(this)
.setTitle("选择来源")
.setNegativeButton("相册", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
try {
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*");
startActivityForResult(intent, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
})
.setPositiveButton("拍照", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
try {
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri
.fromFile(new File(Environment
.getExternalStorageDirectory(),
"pickedImage.png")));
startActivityForResult(intent, 2);
} catch (Exception e) {
e.printStackTrace();
}
}
}).show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (data == null)
return;
startPhotoZoom(data.getData());
break;
case 2:
if (resultCode != -1) {
return;
}
File temp = new File(Environment.getExternalStorageDirectory()
+ "/pickedImage.png");
startPhotoZoom(Uri.fromFile(temp));
break;
case 3:
if (data == null)
return;
Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 60, stream);
byte[] b = stream.toByteArray();
sendImage(b);
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 150);
intent.putExtra("outputY", 150);
intent.putExtra("return-data", true);
startActivityForResult(intent, 3);
}
private void setClientIds(String clientIdsString) {
clientIdsList = new ArrayList<String>(Arrays.asList(clientIdsString
.split("\\,")));
}
@Override
public boolean onLongClick(View v) {
pBar.setVisibility(View.VISIBLE);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
startRecording();
}
});
thread.run();
return false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
pBar.setVisibility(View.GONE);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
stopRecording();
}
});
thread.run();
}
return false;
}
@Override
public void onLocationUpdated(BDLocation location) {
if (willSendLocation) {
sendLocation(location.getLatitude(), location.getLongitude());
}
willSendLocation = false;
}
}