package com.arrownock.opensource.arrownockers.push; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; 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.Base64; 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 com.arrownock.opensource.arrownockers.R; import com.arrownock.opensource.arrownockers.push.PushDetailsEntity.EntityType; import com.arrownock.opensource.arrownockers.utils.AnUtils; import com.arrownock.opensource.arrownockers.utils.CustomReceiver; import com.arrownock.opensource.arrownockers.utils.CustomReceiver.OnPushArrived; import com.arrownock.opensource.arrownockers.utils.DBManager; import com.arrownock.opensource.arrownockers.utils.DBManager.Push; 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; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; // 发送上行Push消息,以当前用户的username作为channel,将Push消息发送给自己 public class PushSendActivity extends Activity implements OnClickListener, OnLongClickListener, OnTouchListener, OnLocationUpdated, OnPushArrived { private Button mBtnSend; private Button mBtnImage; private Button mBtnAudio; private EditText mEditTextContent; private ListView mListView; private PushDetailsListAdapter mAdapter; private List<PushDetailsEntity> mDataArrays; private MediaRecorder recorder; private boolean recording = false; private boolean willSendLocation = false; private List<String> channels; private boolean alive = false; private ProgressBar pBar; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_push_send); getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); channels = new ArrayList<String>(); if (AnUtils.getCurrentUsername() != null) { channels.add(AnUtils.getCurrentUsername()); } initView(); initData(); recorder = null; MapCallback.setPushSendActivity(PushSendActivity.this); CustomReceiver.setPushSendActivity(PushSendActivity.this); } public void addPush(boolean income, String dataType, String message, byte[] binary, double latitude, double longitude) { Push push = new Push(); push.type = "type"; push.dataType = dataType; push.messageId = "messageId"; push.batchNumber = "batchNumber"; push.income = false; push.time = AnUtils.getTimeString(new Date()); if (dataType.equals("text")) { push.binary = null; push.message = message; } else if (dataType.equals("image") || dataType.equals("audio")) { push.binary = binary; push.message = null; } else if (dataType.equals("location")) { push.latitude = latitude; push.longitude = longitude; } push.title = AnUtils.getCurrentUsername(); push.status = "sent"; DBManager.addPush(push); } public void addNewMessage(final boolean income, String message) { PushDetailsEntity entity = new PushDetailsEntity(); entity.dateString = AnUtils.getTimeString(new Date()); entity.isComMsg = income; entity.entityType = EntityType.ET_TEXT; entity.text = message; mDataArrays.add(entity); refresh(income); if (!income) { addPush(income, "text", message, null, 0, 0); } } public void addNewLocation(final boolean income, double lat, double lon) { PushDetailsEntity entity = new PushDetailsEntity(); entity.dateString = AnUtils.getTimeString(new Date()); entity.isComMsg = income; entity.entityType = EntityType.ET_LOCATION; entity.text = "Location..."; entity.latitude = lat; entity.longitude = lon; mDataArrays.add(entity); refresh(income); if (!income) { addPush(income, "location", "Location...", null, lat, lon); } } public void addNewImage(boolean income, byte[] bytes) { PushDetailsEntity entity = new PushDetailsEntity(); entity.dateString = AnUtils.getTimeString(new Date()); entity.isComMsg = income; entity.entityType = EntityType.ET_IMAGE; entity.imageBytes = bytes; mDataArrays.add(entity); refresh(income); if (!income) { addPush(income, "image", null, bytes, 0, 0); } } public void addNewAudio(boolean income, byte[] bytes) { PushDetailsEntity entity = new PushDetailsEntity(); entity.dateString = AnUtils.getTimeString(new Date()); entity.isComMsg = income; entity.entityType = EntityType.ET_AUDIO; entity.audioBytes = bytes; mDataArrays.add(entity); refresh(income); if (income) { playAudio(bytes); } if (!income) { addPush(income, "audio", null, bytes, 0, 0); } } public void playAudio(byte[] bytes) { String pathString = Environment.getExternalStorageDirectory().getPath() + "/receivedPushAudio.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(); final FileInputStream fis = new FileInputStream(pathString); MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() { public void onCompletion(MediaPlayer mp) { mp.release(); try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }; mp.setOnCompletionListener(listener); mp.setDataSource(fis.getFD()); mp.prepare(); mp.start(); } catch (Exception e) { e.printStackTrace(); } } public void startRecording() { if (recording == true) return; try { if (recorder == null) { String pathString = Environment.getExternalStorageDirectory() .getPath() + "/recordedPushAudio.m4a"; recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); recorder.setOutputFile(pathString); recorder.prepare(); recorder.start(); } } catch (Exception e) { e.printStackTrace(); } recording = true; } public void stopRecording() { if (!recording) { return; } try { String pathString = Environment.getExternalStorageDirectory() .getPath() + "/recordedPushAudio.m4a"; File file = new File(pathString); FileInputStream iStream; recorder.stop(); recording = false; recorder.reset(); recorder.release(); recorder = null; iStream = new FileInputStream(file); sendAudio(IOUtils.toByteArray(iStream)); } catch (Exception e) { e.printStackTrace(); } } private void refresh(final boolean income) { runOnUiThread(new Runnable() { @Override public void run() { if (!income) { mEditTextContent.setText(""); } mAdapter.notifyDataSetChanged(); mListView.setSelection(mListView.getCount() - 1); } }); } public void initView() { pBar = (ProgressBar) findViewById(R.id.progressBar); mListView = (ListView) findViewById(R.id.listview); mBtnSend = (Button) findViewById(R.id.btn_send); mBtnSend.setOnClickListener(PushSendActivity.this); mBtnImage = (Button) findViewById(R.id.btn_sendImage); mBtnImage.setOnClickListener(PushSendActivity.this); mBtnAudio = (Button) findViewById(R.id.btn_sendAudio); mBtnAudio.setOnLongClickListener(PushSendActivity.this); mBtnAudio.setOnTouchListener(PushSendActivity.this); mEditTextContent = (EditText) findViewById(R.id.et_sendmessage); mDataArrays = new ArrayList<PushDetailsEntity>(); mAdapter = new PushDetailsListAdapter(this, mDataArrays); mListView.setAdapter(mAdapter); } public void initData() { List<Push> pushList = DBManager.getPushes(AnUtils.getCurrentUsername()); if (pushList == null) { return; } mDataArrays.clear(); for (Push push : pushList) { PushDetailsEntity pushDetailsEntity = new PushDetailsEntity(); pushDetailsEntity.dateString = push.time; pushDetailsEntity.isComMsg = push.income; String dataType = push.dataType; if (dataType.equals("image")) { pushDetailsEntity.entityType = EntityType.ET_IMAGE; pushDetailsEntity.imageBytes = push.binary; } else if (dataType.equals("audio")) { pushDetailsEntity.entityType = EntityType.ET_AUDIO; pushDetailsEntity.audioBytes = push.binary; } else if (dataType.equals("text")) { pushDetailsEntity.entityType = EntityType.ET_TEXT; pushDetailsEntity.text = push.message; } else if (dataType.equals("location")) { pushDetailsEntity.entityType = EntityType.ET_LOCATION; pushDetailsEntity.text = push.message; pushDetailsEntity.latitude = push.latitude; pushDetailsEntity.longitude = push.longitude; } mDataArrays.add(pushDetailsEntity); } mAdapter.notifyDataSetChanged(); mListView.setSelection(mListView.getCount() - 1); DBManager.setPushRead(AnUtils.getCurrentUsername()); } public void handlePushMsg(String payload) { try { JSONObject jsonObject = new JSONObject(payload); jsonObject = jsonObject.getJSONObject("android"); String alertString = jsonObject.getString("alert"); String dataType = null; if (jsonObject.has("type")) { if (jsonObject.getString("type").equals("rich_push")) { dataType = "rich"; } } else { dataType = jsonObject.getString("dataType"); } TextView titleTextView = (TextView) this .findViewById(R.id.tv_title); titleTextView.setText("title"); if (dataType.equals("text")) { addNewMessage(true, alertString); } else if (dataType.equals("image")) { byte[] byteArray = Base64.decode(alertString, Base64.DEFAULT); addNewImage(true, byteArray); } else if (dataType.equals("audio")) { byte[] byteArray = Base64.decode(alertString, Base64.DEFAULT); addNewAudio(true, byteArray); } else if (dataType.equals("rich")) { addNewMessage(true, alertString); } } catch (Exception e) { e.printStackTrace(); } } @Override protected void onResume() { super.onResume(); alive = true; } @Override protected void onDestroy() { super.onDestroy(); alive = false; MapCallback.setPushSendActivity(null); } @Override protected void onStop() { super.onStop(); alive = false; } @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 sendPush(String dataType, String contentString, double latitude, double longitude) { AsyncHttpClient client = new AsyncHttpClient(); JSONObject jsonObject = new JSONObject(); RequestParams params = new RequestParams(); try { if (dataType.equals("location")) { jsonObject.put("alert", "new location"); addNewLocation(false, latitude, longitude); } else { jsonObject.put("alert", contentString); } jsonObject.put("badge", 1); jsonObject.put("vibrate", true); jsonObject.put("title", AnUtils.spf.getString("username", "username")); jsonObject.put("icon", "default"); jsonObject.put("sound", "default"); JSONObject payloadJson = new JSONObject(); payloadJson.put("android", jsonObject); JSONObject typeJson = new JSONObject(); typeJson.put("dataType", dataType); if (dataType.equals("location")) { typeJson.put("latitude", latitude); typeJson.put("longitude", longitude); } payloadJson.put("custom_data", typeJson); params.put("payload", payloadJson.toString()); if (channels.size() == 0) { AnUtils.showToast(PushSendActivity.this, "发送失败,未注册push服务器", Gravity.CENTER, true); return; } String channelsString = StringUtils.join(channels, ","); params.put("channel", channelsString); client.post(AnUtils.pushEndpoint, params, new AsyncHttpResponseHandler() { @Override public void onSuccess(String response) { AnUtils.showToast(PushSendActivity.this, "发送成功", Gravity.CENTER, alive); } @Override public void onFailure(Throwable arg0, String arg1) { AnUtils.showToast(PushSendActivity.this, "发送失败", Gravity.CENTER, alive); } }); } catch (Exception e) { e.printStackTrace(); } } public void sendText() { String contString = mEditTextContent.getText().toString(); if (contString == null || contString.trim().equals("")) { return; } sendPush("text", contString, 0, 0); addNewMessage(false, contString); } public void sendImage(byte[] bytes) { addNewImage(false, bytes); String base64String = Base64.encodeToString(bytes, Base64.DEFAULT); sendPush("image", base64String, 0, 0); } public void sendAudio(byte[] bytes) { addNewAudio(false, bytes); String base64String = Base64.encodeToString(bytes, Base64.DEFAULT); sendPush("audio", base64String, 0, 0); } public void sendLocation(View view) { willSendLocation = true; if (AnUtils.mapClient != null && AnUtils.mapClient.isStarted()) { AnUtils.mapClient.requestLocation(); } else { AnUtils.showToast(PushSendActivity.this, "位置服务模块未启动", Gravity.CENTER, alive); willSendLocation = false; } } private void ShowPickDialog() { new AlertDialog.Builder(PushSendActivity.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(), "cameraImage.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() + "/cameraImage.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); } public void showMore(View view) { RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_bottom); rl.setVisibility(View.INVISIBLE); rl = (RelativeLayout) findViewById(R.id.rl_more); rl.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) { RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_more); rl.setVisibility(View.INVISIBLE); rl = (RelativeLayout) findViewById(R.id.rl_bottom); rl.setVisibility(View.VISIBLE); } @Override public boolean onLongClick(View v) { pBar.setVisibility(View.VISIBLE); Thread thread = new Thread(new Runnable() { @Override public void run() { startRecording(); } }); thread.start(); 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.start(); } return false; } @Override public void onLocationUpdated(BDLocation location) { if (willSendLocation) { sendPush("location", null, location.getLatitude(), location.getLongitude()); } willSendLocation = false; } public void showMap(double latitude, double longitude) { Intent intent = new Intent(this, MapActivity.class); intent.putExtra("latitude", latitude); intent.putExtra("longitude", longitude); startActivity(intent); } public void handleTap(final View view) { ImageView tv = (ImageView) view; PushDetailsEntity pushDetailsEntity = (PushDetailsEntity) tv.getTag(); EntityType type = pushDetailsEntity.entityType; switch (type) { case ET_AUDIO: playAudio(pushDetailsEntity.audioBytes); break; case ET_LOCATION: showMap(pushDetailsEntity.latitude, pushDetailsEntity.longitude); default: break; } } @Override public void onPushSaved() { initData(); } @Override public void onPushSaved(String message) { } }