package com.fanxin.huangfangyi.main.ulive.upload; import android.app.ProgressDialog; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.ScaleAnimation; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.fanxin.huangfangyi.DemoApplication; import com.fanxin.huangfangyi.R; import com.fanxin.huangfangyi.main.FXConstant; import com.fanxin.huangfangyi.main.adapter.LiveMessageAdapter; import com.fanxin.huangfangyi.main.ulive.preference.Log2FileUtil; import com.fanxin.huangfangyi.main.ulive.preference.Settings; import com.fanxin.huangfangyi.ui.BaseActivity; import com.fanxin.easeui.EaseConstant; import com.fanxin.easeui.controller.EaseUI; import com.fanxin.easeui.utils.EaseCommonUtils; import com.hyphenate.EMMessageListener; import com.hyphenate.EMValueCallBack; import com.hyphenate.chat.EMChatRoom; import com.hyphenate.chat.EMClient; import com.hyphenate.chat.EMConversation; import com.hyphenate.chat.EMMessage; import com.ucloud.common.util.DeviceUtils; import com.ucloud.common.util.StringUtil; import com.ucloud.live.UEasyStreaming; import com.ucloud.live.UStreamingProfile; import com.ucloud.live.widget.UAspectFrameLayout; import java.util.List; public abstract class BasePublishDemo extends BaseActivity implements UEasyStreaming.UStreamingStateListener { private static final String TAG = "BasePublishDemo"; public static final int MSG_UPDATE_COUNTDOWN = 1; public static final int COUNTDOWN_DELAY = 1000; public static final int COUNTDOWN_START_INDEX = 3; public static final int COUNTDOWN_END_INDEX = 1; protected Settings mSettings; protected String rtmpPushStreamDomain = "publish3.cdn.ucloud.com.cn"; //Views protected ImageView mCameraToggleIv; protected ImageView mLampToggleIv; protected ImageButton mCloseRecorderImgBtn; protected ImageButton mToggleFilterImgBtn; protected Button mBackImgBtn; protected View mFocusIndex; protected TextView mBitrateTxtv; protected TextView mCountDownTxtv; protected TextView mRecordedTimeTxtv; protected TextView mOutputStreamInfoTxtv; protected TextView mBufferOverfloInfoTxtv; protected ViewGroup mContainer; protected UAspectFrameLayout mPreviewContainer; protected boolean isShutDownCountdown = false; protected UEasyStreaming mEasyStreaming; protected UStreamingProfile mStreamingProfile; protected UiHandler uiHandler; public abstract void initEnv(); private ListView listView; private int chatType = EaseConstant.CHATTYPE_CHATROOM; private String toChatUsername; private Button btn_send; private EditText et_content; private List<EMMessage> msgList; LiveMessageAdapter adapter; private EMConversation conversation; protected int pagesize = 20; private ProgressDialog progressDialog; @Override public void onStateChanged(int type, Object event) { switch (type) { case UEasyStreaming.State.START_PREVIEW: Log.i(TAG, event.toString()); handleShowStreamingInfo(); if (this instanceof PublishDemo4MediaCodec) { mEasyStreaming.applyFilter(UEasyStreaming.FILTER_BEAUTIFY_HIGH_PERFORMANCE); // mEasyStreaming.applyFilter(UEasyStreaming.FILTER_BEAUTIFY); } break; case UEasyStreaming.State.START_RECORDING: Log.i(TAG, event.toString()); break; case UEasyStreaming.State.BUFFER_OVERFLOW: mBufferOverfloInfoTxtv.setText("unstable network stats:" + mEasyStreaming.getNetworkUnstableStats()); Log.w(TAG, "unstable network"); Toast.makeText(this, "unstable network", Toast.LENGTH_SHORT).show(); break; case UEasyStreaming.State.MEDIA_MUXER_PREPARED_ERROR: Log.e(TAG, "prepare error, the publish stream id may be reuse, server error or network disconnect, try change one."); Toast.makeText(this, "the publish stream id may be reuse, server error or network disconnect, try change one.", Toast.LENGTH_LONG).show(); break; case UEasyStreaming.State.MEDIA_MUXER_PREPARED_SUCCESS: Log.i(TAG, event.toString()); break; case UEasyStreaming.State.MEDIA_INFO_SIGNATRUE_FAILED: Toast.makeText(this, event.toString(), Toast.LENGTH_LONG).show(); break; case UEasyStreaming.State.MEDIA_INFO_NETWORK_SPEED: if (mBitrateTxtv != null) { mBitrateTxtv.setVisibility(View.VISIBLE); long speed = Long.valueOf(event.toString()); if (speed > 1024) { mBitrateTxtv.setText(speed / 1024 + "K/s"); } else { mBitrateTxtv.setText(speed + "B/s"); } } break; case UEasyStreaming.State.MEDIA_INFO_PUBLISH_STREAMING_TIME: if (mRecordedTimeTxtv != null) { mRecordedTimeTxtv.setVisibility(View.VISIBLE); long time = Long.valueOf(event.toString()); String retVal = StringUtil.getTimeFormatString(time); mRecordedTimeTxtv.setText(retVal); } break; case UEasyStreaming.State.MEDIA_ERROR_CAMERA_PREVIEW_SIZE_UNSUPPORT: Log.e(TAG, "MEDIA_ERROR_CAMERA_PREVIEW:" + event.toString()); break; } } private class UiHandler extends Handler { public UiHandler(Looper looper) { super(looper); } public void handleMessage(Message msg) { switch (msg.what) { case MSG_UPDATE_COUNTDOWN: handleUpdateCountdown(msg.arg1); break; } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); progressDialog=new ProgressDialog(this); progressDialog.setMessage("正在进入直播间..."); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setCanceledOnTouchOutside(false); progressDialog.show(); mSettings = new Settings(this); setContentView(R.layout.live_layout_live_room_view); getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); if (mSettings.getVideoCaptureOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } init(); new Thread(){ public void run() { int i = COUNTDOWN_START_INDEX; do { try { Thread.sleep(COUNTDOWN_DELAY); } catch (InterruptedException e) { e.printStackTrace(); } Message msg = Message.obtain(); msg.what = MSG_UPDATE_COUNTDOWN; msg.arg1 = i; uiHandler.sendMessage(msg); i--; }while(i >= COUNTDOWN_END_INDEX); } }.start(); initViewChat(); } private void init() { uiHandler = new UiHandler(getMainLooper()); initView(); initEnv(); } private void initViewChat(){ toChatUsername = FXConstant.FXLIVE_CHATROOM_ID; listView = (ListView) findViewById(R.id.list); listView.getBackground().setAlpha(100); btn_send = (Button) this.findViewById(R.id.btn_send); et_content = (EditText) this.findViewById(R.id.et_content); EMClient.getInstance().chatroomManager().joinChatRoom(toChatUsername, new EMValueCallBack<EMChatRoom>() { @Override public void onSuccess(EMChatRoom emChatRoom) { runOnUiThread(new Runnable() { @Override public void run() { getAllMessage(); } }); } @Override public void onError(int i, String s) { runOnUiThread(new Runnable() { @Override public void run() { if(progressDialog!=null&&progressDialog.isShowing()){ progressDialog.dismiss(); Toast.makeText(getApplicationContext(),"初始化互动模块失败...",Toast.LENGTH_SHORT).show(); } } }); } }); } private void initView() { mCameraToggleIv = (ImageView) findViewById(R.id.img_bt_switch_camera); mLampToggleIv = (ImageView) findViewById(R.id.img_bt_lamp); mCloseRecorderImgBtn = (ImageButton) findViewById(R.id.img_bt_close_record); mFocusIndex = findViewById(R.id.focus_index); mBitrateTxtv = (TextView) findViewById(R.id.bitrate_txtv); mPreviewContainer = (UAspectFrameLayout)findViewById(R.id.container); mCountDownTxtv = (TextView) findViewById(R.id.countdown_txtv); mRecordedTimeTxtv = (TextView) findViewById(R.id.recorded_time_txtv); mOutputStreamInfoTxtv = (TextView) findViewById(R.id.output_url_txtv); mToggleFilterImgBtn = (ImageButton) findViewById(R.id.img_bt_filter); mBufferOverfloInfoTxtv = (TextView) findViewById(R.id.network_overflow_count); mBackImgBtn = (Button) findViewById(R.id.btn_finish); mContainer = (ViewGroup) findViewById(R.id.live_finish_container); mCameraToggleIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mEasyStreaming != null) { mEasyStreaming.switchCamera(); } } }); mLampToggleIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mEasyStreaming != null) { mEasyStreaming.toggleFlashMode(); } } }); mCloseRecorderImgBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { isShutDownCountdown = true; mCloseRecorderImgBtn.setEnabled(false); if (mEasyStreaming != null) { mEasyStreaming.stopRecording(); } mContainer.setVisibility(View.VISIBLE); } }); mToggleFilterImgBtn.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if (BasePublishDemo.this instanceof PublishDemo4MediaCodec) { mEasyStreaming.toggleFilter(); } else { Toast.makeText(BasePublishDemo.this, "Sorry, just support for mediacodec.", Toast.LENGTH_SHORT).show(); } } }); mBackImgBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } @Override protected void onPause() { super.onPause(); mEasyStreaming.onPause(); } @Override protected void onResume() { super.onResume(); mEasyStreaming.onResume(); } @Override protected void onDestroy() { super.onDestroy(); if(mSettings.isOpenLogRecoder()) { Log2FileUtil.getInstance().stopLog(); } mEasyStreaming.onDestory(); EMClient.getInstance().chatManager().removeMessageListener(msgListener); } public String bitrateMode(int value) { switch (value) { case UStreamingProfile.VIDEO_BITRATE_LOW: return "VIDEO_BITRATE_LOW"; case UStreamingProfile.VIDEO_BITRATE_NORMAL: return "VIDEO_BITRATE_NORMAL"; case UStreamingProfile.VIDEO_BITRATE_MEDIUM: return "VIDEO_BITRATE_MEDIUM"; case UStreamingProfile.VIDEO_BITRATE_HIGH: return "VIDEO_BITRATE_HIGH"; default: return value +""; } } public void handleShowStreamingInfo() { if (mOutputStreamInfoTxtv != null) { mOutputStreamInfoTxtv.setVisibility(View.VISIBLE); String info = "video width:" + mSettings.getVideoCaptureWidth()+ "\n" + "video height:" + mSettings.getVideoCaptureHeight() + "\n" + "video bitrate:" + bitrateMode(mSettings.getVideoEncodingBitRate()) + "\n" + "video fps:" + mSettings.getVideoFrameRate() + "\n" + "url:" + "rtmp://" + mStreamingProfile.getStream().getPublishDomain() + "/" + mStreamingProfile.getStream().getStreamId() + "\n" + "brand:" + DeviceUtils.getDeviceBrand() + "_" + DeviceUtils.getDeviceModel() + "\n" + "sdk version:" + com.ucloud.live.Build.VERSION + "\n" + "android sdk version:" + android.os.Build.VERSION.SDK_INT + "\n" + "codec type:" + (BasePublishDemo.this instanceof PublishDemo4MediaCodec ? "mediacodec" : "x264") + "\n"; mOutputStreamInfoTxtv.setText(info); Log.e(TAG, "@@" + info); } } public void handleUpdateCountdown(final int count) { if (mCountDownTxtv != null) { mCountDownTxtv.setVisibility(View.VISIBLE); mCountDownTxtv.setText(String.format("%d", count)); ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f,0f, 1.0f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation.setDuration(COUNTDOWN_DELAY); scaleAnimation.setFillAfter(false); scaleAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mCountDownTxtv.setVisibility(View.GONE); if (count == COUNTDOWN_END_INDEX && mEasyStreaming != null && !isShutDownCountdown) { mEasyStreaming.startRecording(); } } @Override public void onAnimationRepeat(Animation animation) { } }); if (!isShutDownCountdown) { mCountDownTxtv.startAnimation(scaleAnimation); } else { mCountDownTxtv.setVisibility(View.GONE); } } } protected void getAllMessage() { // 获取当前conversation对象 conversation = EMClient.getInstance().chatManager().getConversation(toChatUsername, EaseCommonUtils.getConversationType(chatType), true); // 把此会话的未读数置为0 conversation.markAllMessagesAsRead(); // 初始化db时,每个conversation加载数目是getChatOptions().getNumberOfMessagesLoaded // 这个数目如果比用户期望进入会话界面时显示的个数不一样,就多加载一些 final List<EMMessage> msgs = conversation.getAllMessages(); int msgCount = msgs != null ? msgs.size() : 0; if (msgCount < conversation.getAllMsgCount() && msgCount < pagesize) { String msgId = null; if (msgs != null && msgs.size() > 0) { msgId = msgs.get(0).getMsgId(); } conversation.loadMoreMsgFromDB(msgId, pagesize - msgCount); } msgList = conversation.getAllMessages(); adapter = new LiveMessageAdapter(msgList, BasePublishDemo.this); listView.setAdapter(adapter); listView.setSelection(listView.getCount() - 1); btn_send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String content = et_content.getText().toString().trim(); if (TextUtils.isEmpty(content)) { return; } setMesaage(content); } }); EMClient.getInstance().chatManager().addMessageListener(msgListener); if(progressDialog!=null&&progressDialog.isShowing()){ progressDialog.dismiss(); } } private void setMesaage(String content) { // 创建一条文本消息,content为消息文字内容,toChatUsername为对方用户或者群聊的id,后文皆是如此 EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername); // 如果是群聊,设置chattype,默认是单聊 if (chatType == EaseConstant.CHATTYPE_CHATROOM) message.setChatType(EMMessage.ChatType.ChatRoom); message.setAttribute(FXConstant.KEY_USER_INFO, DemoApplication.getInstance().getUserJson().toJSONString()); // 发送消息 EMClient.getInstance().chatManager().sendMessage(message); msgList.add(message); adapter.notifyDataSetChanged(); if (msgList.size() > 0) { listView.setSelection(listView.getCount() - 1); } et_content.setText(""); } EMMessageListener msgListener = new EMMessageListener() { @Override public void onMessageReceived(List<EMMessage> messages) { for (EMMessage message : messages) { String username = null; // 群组消息 if (message.getChatType() == EMMessage.ChatType.GroupChat || message.getChatType() == EMMessage.ChatType.ChatRoom) { username = message.getTo(); } else { // 单聊消息 username = message.getFrom(); } // 如果是当前会话的消息,刷新聊天页面 if (username.equals(toChatUsername)) { msgList.addAll(messages); adapter.notifyDataSetChanged(); if (msgList.size() > 0) { et_content.setSelection(listView.getCount() - 1); } }else { // 如果消息不是和当前聊天ID的消息 EaseUI.getInstance().getNotifier().onNewMsg(message); } } // 收到消息 } @Override public void onCmdMessageReceived(List<EMMessage> messages) { // 收到透传消息 } @Override public void onMessageReadAckReceived(List<EMMessage> messages) { // 收到已读回执 } @Override public void onMessageDeliveryAckReceived(List<EMMessage> message) { // 收到已送达回执 } @Override public void onMessageChanged(EMMessage message, Object change) { // 消息状态变动 } }; }