Commit eac85ca3943385208f3b0ae72ae21e02179dbecd
1 parent
96ab3599
推流功能页面代码迁移
Showing
72 changed files
with
1734 additions
and
1 deletions
app/build.gradle
| ... | ... | @@ -25,5 +25,8 @@ android { |
| 25 | 25 | dependencies { |
| 26 | 26 | compile fileTree(dir: 'libs', include: ['*.jar']) |
| 27 | 27 | compile 'com.android.support:appcompat-v7:26.+' |
| 28 | + compile 'com.android.support:recyclerview-v7:26.+' | |
| 29 | + | |
| 30 | + compile 'com.google.code.gson:gson:2.7' | |
| 28 | 31 | compile 'com.android.support.constraint:constraint-layout:1.0.2' |
| 29 | 32 | } | ... | ... |
app/libs/libcnlivelive.jar
0 → 100644
No preview for this file type
app/libs/libcnliveutil.jar
0 → 100644
No preview for this file type
app/src/main/AndroidManifest.xml
| ... | ... | @@ -2,6 +2,22 @@ |
| 2 | 2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | 3 | package="com.cnlive.gundam"> |
| 4 | 4 | |
| 5 | + <uses-permission android:name="android.permission.GET_TASKS" /> | |
| 6 | + <uses-permission android:name="android.permission.VIBRATE" /> | |
| 7 | + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> | |
| 8 | + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | |
| 9 | + <uses-permission android:name="android.permission.INTERNET" /> | |
| 10 | + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |
| 11 | + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |
| 12 | + <uses-permission android:name="android.permission.RECORD_AUDIO" /> | |
| 13 | + <uses-permission android:name="android.permission.CAMERA" /> | |
| 14 | + <uses-permission android:name="android.permission.WAKE_LOCK" /> | |
| 15 | + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | |
| 16 | + <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> | |
| 17 | + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | |
| 18 | + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> | |
| 19 | + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | |
| 20 | + | |
| 5 | 21 | <application |
| 6 | 22 | android:allowBackup="true" |
| 7 | 23 | android:icon="@mipmap/ic_launcher" |
| ... | ... | @@ -16,6 +32,14 @@ |
| 16 | 32 | <category android:name="android.intent.category.LAUNCHER" /> |
| 17 | 33 | </intent-filter> |
| 18 | 34 | </activity> |
| 35 | + | |
| 36 | + | |
| 37 | + <activity | |
| 38 | + android:name=".stream.ui.activity.StreamActivity" | |
| 39 | + android:configChanges="orientation|keyboardHidden|screenSize" | |
| 40 | + android:launchMode="singleTop" | |
| 41 | + android:screenOrientation="portrait" | |
| 42 | + android:theme="@style/Theme.AppCompat.Light.NoActionBar" /> | |
| 19 | 43 | </application> |
| 20 | 44 | |
| 21 | 45 | </manifest> |
| 22 | 46 | \ No newline at end of file | ... | ... |
app/src/main/java/com/cnlive/gundam/main/ui/activity/MainActivity.java
| 1 | 1 | package com.cnlive.gundam.main.ui.activity; |
| 2 | 2 | |
| 3 | +import android.content.Intent; | |
| 3 | 4 | import android.databinding.DataBindingUtil; |
| 4 | 5 | import android.os.Bundle; |
| 5 | 6 | import android.support.v7.app.AppCompatActivity; |
| ... | ... | @@ -11,6 +12,7 @@ import com.cnlive.gundam.main.ui.fragment.HomeFragment; |
| 11 | 12 | import com.cnlive.gundam.main.ui.fragment.LiveFragment; |
| 12 | 13 | import com.cnlive.gundam.main.ui.fragment.UGCListFragment; |
| 13 | 14 | import com.cnlive.gundam.main.ui.widget.FragmentTabHost; |
| 15 | +import com.cnlive.gundam.stream.ui.activity.StreamActivity; | |
| 14 | 16 | |
| 15 | 17 | import java.util.Arrays; |
| 16 | 18 | |
| ... | ... | @@ -39,9 +41,16 @@ public class MainActivity extends AppCompatActivity implements FragmentTabHost.O |
| 39 | 41 | public boolean onSetCurrentTab(String tag) { |
| 40 | 42 | switch (tag) { |
| 41 | 43 | case "stream": |
| 42 | - //TODO 启动直播推流页面0 | |
| 44 | + Intent intent = new Intent(this, StreamActivity.class); | |
| 45 | + intent.putExtra("activityId", ""+System.currentTimeMillis()); | |
| 46 | + intent.putExtra("channelId", "androidtest"); | |
| 47 | + intent.putExtra("channelName", "androidTest"); | |
| 48 | + intent.putExtra("coverImgUrl", ""); | |
| 49 | + intent.putExtra("landscape", false); | |
| 50 | + startActivity(intent); | |
| 43 | 51 | return true; |
| 44 | 52 | } |
| 45 | 53 | return false; |
| 46 | 54 | } |
| 55 | + | |
| 47 | 56 | } |
| 48 | 57 | \ No newline at end of file | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/model/ChatItem.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by Lynn on 5/24/2017. | |
| 5 | + */ | |
| 6 | + | |
| 7 | +public class ChatItem { | |
| 8 | + private String headUrl; | |
| 9 | + private String userName; | |
| 10 | + private String content; | |
| 11 | + | |
| 12 | + public ChatItem() { | |
| 13 | + | |
| 14 | + } | |
| 15 | + | |
| 16 | + public ChatItem(String headUrl, String userName, String content) { | |
| 17 | + this.headUrl = headUrl; | |
| 18 | + this.userName = userName; | |
| 19 | + this.content = content; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public String getHeadUrl() { | |
| 23 | + return headUrl == null ? " " : headUrl; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setHeadUrl(String headUrl) { | |
| 27 | + this.headUrl = headUrl; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public String getUserName() { | |
| 31 | + return userName; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setUserName(String userName) { | |
| 35 | + this.userName = userName; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public String getContent() { | |
| 39 | + return content; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void setContent(String content) { | |
| 43 | + this.content = content; | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + public String toString() { | |
| 48 | + return "ChatItem{" + | |
| 49 | + "headUrl='" + headUrl + '\'' + | |
| 50 | + ", userName='" + userName + '\'' + | |
| 51 | + ", content='" + content + '\'' + | |
| 52 | + '}'; | |
| 53 | + } | |
| 54 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/model/ExtensionModel.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by Lynn on 5/26/2017. | |
| 5 | + */ | |
| 6 | + | |
| 7 | +public class ExtensionModel { | |
| 8 | + private String name; | |
| 9 | + private String iconUrl; | |
| 10 | + | |
| 11 | + public ExtensionModel() { | |
| 12 | + } | |
| 13 | + | |
| 14 | + public ExtensionModel(String name, String iconUrl) { | |
| 15 | + this.name = name; | |
| 16 | + this.iconUrl = iconUrl; | |
| 17 | + } | |
| 18 | + | |
| 19 | + public String getName() { | |
| 20 | + return name; | |
| 21 | + } | |
| 22 | + | |
| 23 | + public void setName(String name) { | |
| 24 | + this.name = name; | |
| 25 | + } | |
| 26 | + | |
| 27 | + public String getIconUrl() { | |
| 28 | + return iconUrl; | |
| 29 | + } | |
| 30 | + | |
| 31 | + public void setIconUrl(String iconUrl) { | |
| 32 | + this.iconUrl = iconUrl; | |
| 33 | + } | |
| 34 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/model/ShowView.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by Lynn on 5/23/2017. | |
| 5 | + */ | |
| 6 | + | |
| 7 | +public class ShowView { | |
| 8 | + //开始直播按钮 | |
| 9 | + private boolean startBtn = true; | |
| 10 | + //结束页面 | |
| 11 | + private boolean endLayout = false; | |
| 12 | + //重试页面 | |
| 13 | + private boolean retryLayout = false; | |
| 14 | + //结束页面的提示文字(红色文字) | |
| 15 | + private boolean msgHint = false; | |
| 16 | + //自动重连提示文字(黄色文字) | |
| 17 | + private boolean autoRecMsg = false; | |
| 18 | + //推流美颜等按钮的显示 | |
| 19 | + private boolean recordBtns = true; | |
| 20 | + //美颜按钮 | |
| 21 | + private boolean beautifulBtn = false; | |
| 22 | + //闪光灯 | |
| 23 | + private boolean flashBtn = false; | |
| 24 | + //聊天recyclerview | |
| 25 | + private boolean chatView = false; | |
| 26 | + //聊天室人数 | |
| 27 | + private boolean viewers = false; | |
| 28 | + | |
| 29 | + //自动重连的提示文字 | |
| 30 | + private boolean autoRectTxt; | |
| 31 | + | |
| 32 | + public ShowView() { | |
| 33 | + } | |
| 34 | + | |
| 35 | + public boolean isStartBtn() { | |
| 36 | + return startBtn; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public void setStartBtn(boolean startBtn) { | |
| 40 | + this.startBtn = startBtn; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public boolean isEndLayout() { | |
| 44 | + return endLayout; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public void setEndLayout(boolean endLayout) { | |
| 48 | + this.endLayout = endLayout; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public boolean isRetryLayout() { | |
| 52 | + return retryLayout; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public void setRetryLayout(boolean retryLayout) { | |
| 56 | + this.retryLayout = retryLayout; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public boolean isMsgHint() { | |
| 60 | + return msgHint; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public void setMsgHint(boolean msgHint) { | |
| 64 | + this.msgHint = msgHint; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public boolean isAutoRecMsg() { | |
| 68 | + return autoRecMsg; | |
| 69 | + } | |
| 70 | + | |
| 71 | + public void setAutoRecMsg(boolean autoRecMsg) { | |
| 72 | + this.autoRecMsg = autoRecMsg; | |
| 73 | + } | |
| 74 | + | |
| 75 | + public boolean isAutoRectTxt() { | |
| 76 | + return autoRectTxt; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public boolean isRecordBtns() { | |
| 80 | + return recordBtns; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public void setRecordBtns(boolean recordBtns) { | |
| 84 | + this.recordBtns = recordBtns; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public boolean isBeautifulBtn() { | |
| 88 | + return beautifulBtn; | |
| 89 | + } | |
| 90 | + | |
| 91 | + public void setBeautifulBtn(boolean beautifulBtn) { | |
| 92 | + this.beautifulBtn = beautifulBtn; | |
| 93 | + } | |
| 94 | + | |
| 95 | + public boolean isFlashBtn() { | |
| 96 | + return flashBtn; | |
| 97 | + } | |
| 98 | + | |
| 99 | + public void setFlashBtn(boolean flashBtn) { | |
| 100 | + this.flashBtn = flashBtn; | |
| 101 | + } | |
| 102 | + | |
| 103 | + public void setAutoRectTxt(boolean autoRectTxt) { | |
| 104 | + this.autoRectTxt = autoRectTxt; | |
| 105 | + } | |
| 106 | + | |
| 107 | + public boolean isChatView() { | |
| 108 | + return chatView; | |
| 109 | + } | |
| 110 | + | |
| 111 | + public void setChatView(boolean chatView) { | |
| 112 | + this.chatView = chatView; | |
| 113 | + } | |
| 114 | + | |
| 115 | + public boolean isViewers() { | |
| 116 | + return viewers; | |
| 117 | + } | |
| 118 | + | |
| 119 | + public void setViewers(boolean viewers) { | |
| 120 | + this.viewers = viewers; | |
| 121 | + } | |
| 122 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/ui/activity/BaseStreamActivity.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.ui.activity; | |
| 2 | + | |
| 3 | +import android.Manifest; | |
| 4 | +import android.app.AlertDialog; | |
| 5 | +import android.app.Dialog; | |
| 6 | +import android.content.DialogInterface; | |
| 7 | +import android.content.Intent; | |
| 8 | +import android.content.pm.ActivityInfo; | |
| 9 | +import android.content.pm.PackageManager; | |
| 10 | +import android.opengl.GLSurfaceView; | |
| 11 | +import android.os.Build; | |
| 12 | +import android.os.Bundle; | |
| 13 | +import android.os.Environment; | |
| 14 | +import android.os.Handler; | |
| 15 | +import android.os.Message; | |
| 16 | +import android.provider.Settings; | |
| 17 | +import android.support.annotation.Nullable; | |
| 18 | +import android.support.v4.app.ActivityCompat; | |
| 19 | +import android.support.v7.app.AppCompatActivity; | |
| 20 | +import android.text.TextUtils; | |
| 21 | +import android.util.Log; | |
| 22 | + | |
| 23 | +import com.cnlive.libs.stream.Streamer; | |
| 24 | +import com.cnlive.libs.stream.base.IStreamer; | |
| 25 | +import com.cnlive.libs.stream.model.ActivityConfig; | |
| 26 | +import com.cnlive.libs.stream.model.Filters; | |
| 27 | + | |
| 28 | +import java.io.File; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * Created by Lynn on 5/16/2017. | |
| 32 | + */ | |
| 33 | + | |
| 34 | +public class BaseStreamActivity extends AppCompatActivity implements Handler.Callback { | |
| 35 | + | |
| 36 | + private static final String TAG = "BaseStreamActivity"; | |
| 37 | + | |
| 38 | + private Streamer mStreamer; | |
| 39 | + | |
| 40 | + protected String reconnect_msg; | |
| 41 | + protected String finish_msg; | |
| 42 | + protected String stop_msg; | |
| 43 | + protected int error_code; | |
| 44 | + | |
| 45 | + protected Handler mHandler; | |
| 46 | + | |
| 47 | + protected boolean isAutoStart = false; | |
| 48 | + | |
| 49 | + private final static int PERMISSION_REQUEST_CAMERA_AUDIOREC = 1; | |
| 50 | + | |
| 51 | + @Override | |
| 52 | + protected void onCreate(@Nullable Bundle savedInstanceState) { | |
| 53 | + super.onCreate(savedInstanceState); | |
| 54 | + | |
| 55 | + mHandler = new Handler(this); | |
| 56 | + } | |
| 57 | + | |
| 58 | + protected void initStreamer(boolean landScape, GLSurfaceView glSurfaceView) { | |
| 59 | + setRequestedOrientation(landScape ? | |
| 60 | + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : | |
| 61 | + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); | |
| 62 | + mStreamer = new Streamer(this); | |
| 63 | + //设置预览编码帧率 | |
| 64 | + mStreamer.setPreviewFps(15); | |
| 65 | + //设置推流编码帧率 | |
| 66 | + mStreamer.setTargetFps(15); | |
| 67 | + //设置最初、最大、最小视频码率 | |
| 68 | + mStreamer.setVideoKBitrate(800 * 3 / 4, 800, 800 / 4); | |
| 69 | + //设置音频编码码率 | |
| 70 | + mStreamer.setAudioKBitrate(48); | |
| 71 | + //设置预览分辨率 | |
| 72 | + mStreamer.setPreviewResolution(IStreamer.VIDEO_RESOLUTION_540P); | |
| 73 | + //设置推流分辨率 | |
| 74 | + mStreamer.setTargetResolution(IStreamer.VIDEO_RESOLUTION_540P); | |
| 75 | + //设置编码模式 | |
| 76 | + mStreamer.setEncodeMethod(IStreamer.ENCODE_METHOD_SOFTWARE_COMPAT); | |
| 77 | + //设置横竖屏方向 | |
| 78 | + mStreamer.setRotateDegrees(landScape ? 90 : 0); | |
| 79 | + if (landScape) { | |
| 80 | + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横屏 | |
| 81 | + } else { | |
| 82 | + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏 | |
| 83 | + } | |
| 84 | + //设置预览view | |
| 85 | + mStreamer.setDisplayPreview(glSurfaceView); | |
| 86 | + //设置前置摄像头镜像 | |
| 87 | + mStreamer.setFrontCameraMirror(true); | |
| 88 | + //设置水印 | |
| 89 | + String path = Environment.getExternalStorageDirectory() + File.separator + "cnlive_logo.png"; | |
| 90 | + mStreamer.showWaterMarkLogo(path, 0.03f, 0.02f, landScape ? 0.0911f : 0.15f, landScape ? 0.0545f : 0.033f, 1f); | |
| 91 | + //设置视频编码是的帧间隔,默认3秒 | |
| 92 | + mStreamer.setIFrameInterval(2); | |
| 93 | + //设置音频通道 | |
| 94 | + mStreamer.setEnableStreamStatModule(true); | |
| 95 | + //设置自动重连 | |
| 96 | + mStreamer.setEnableAutoRestart(true, 3, 10000); | |
| 97 | + //设置Info回调 | |
| 98 | + mStreamer.setOnInfoListener(mInfoListener); | |
| 99 | + //设置error回调 | |
| 100 | + mStreamer.setOnErrorListener(mErrorListener); | |
| 101 | + } | |
| 102 | + | |
| 103 | + protected void switchCamera() { | |
| 104 | + mStreamer.switchCamera(); | |
| 105 | + } | |
| 106 | + | |
| 107 | + protected boolean isFrontCamera() { | |
| 108 | + return mStreamer.isFrontCamera(); | |
| 109 | + } | |
| 110 | + | |
| 111 | + protected void setFilter(Filters filter) { | |
| 112 | + mStreamer.setFilter(filter.getFilter()); | |
| 113 | + } | |
| 114 | + | |
| 115 | + protected void toggleTorch(boolean b) { | |
| 116 | + mStreamer.toggleTorch(b); | |
| 117 | + } | |
| 118 | + | |
| 119 | + protected boolean isRecording() { | |
| 120 | + return mStreamer.isRecording(); | |
| 121 | + } | |
| 122 | + | |
| 123 | + protected boolean autoRestart() { | |
| 124 | + return mStreamer.getEnableAutoRestart(); | |
| 125 | + } | |
| 126 | + | |
| 127 | + protected int getAutoRestartCount() { | |
| 128 | + return mStreamer.getAutoRestartCount(); | |
| 129 | + } | |
| 130 | + | |
| 131 | + protected boolean startStream(ActivityConfig activityConfig) { | |
| 132 | + // TODO: 5/22/2017 统计 | |
| 133 | + return mStreamer.startStream(activityConfig); | |
| 134 | + } | |
| 135 | + | |
| 136 | + protected boolean stopStream() { | |
| 137 | + // TODO: 5/22/2017 统计 | |
| 138 | + return mStreamer.stopStream(); | |
| 139 | + } | |
| 140 | + | |
| 141 | + @Override | |
| 142 | + protected void onPause() { | |
| 143 | + super.onPause(); | |
| 144 | + if (dialog != null) dialog.dismiss(); | |
| 145 | + mStreamer.setAudioOnly(true); | |
| 146 | + mStreamer.setMuteAudio(true); | |
| 147 | + mStreamer.stopCameraPreview(); | |
| 148 | + mStreamer.pause(); | |
| 149 | + } | |
| 150 | + | |
| 151 | + @Override | |
| 152 | + protected void onResume() { | |
| 153 | + super.onResume(); | |
| 154 | + mStreamer.resume(); | |
| 155 | + startCameraPreviewWithPermCheck(); | |
| 156 | + mStreamer.setAudioOnly(false); | |
| 157 | + mStreamer.setMuteAudio(false); | |
| 158 | + } | |
| 159 | + | |
| 160 | + @Override | |
| 161 | + protected void onDestroy() { | |
| 162 | + super.onDestroy(); | |
| 163 | + mStreamer.release(); | |
| 164 | + mHandler.removeCallbacksAndMessages(null); | |
| 165 | + } | |
| 166 | + | |
| 167 | + @Override | |
| 168 | + public boolean handleMessage(Message message) { | |
| 169 | + reconnect_msg = null; | |
| 170 | + finish_msg = null; | |
| 171 | + stop_msg = null; | |
| 172 | + error_code = message.what; | |
| 173 | + switch (message.what) { | |
| 174 | + case IStreamer.cnstream_camera_init_done: | |
| 175 | + if (mStreamer.isRecording()) | |
| 176 | + if (isAutoStart && !mStreamer.startStream()) | |
| 177 | + stop_msg = "未能开启直播请重试."; | |
| 178 | + break; | |
| 179 | + case IStreamer.cnstream_stop_stream_done: | |
| 180 | + Log.i(TAG, "停止直播活动成功"); | |
| 181 | + break; | |
| 182 | + case IStreamer.cnstream_open_stream_succ: | |
| 183 | + Log.i(TAG, "推流成功"); | |
| 184 | + break; | |
| 185 | + case IStreamer.cnstream_frame_send_slow: | |
| 186 | + Log.i(TAG, "网络状态不佳,数据发送可能有延迟 发送当前帧的时长"); | |
| 187 | + break; | |
| 188 | + case IStreamer.cnstream_est_bw_raise: | |
| 189 | + Log.i(TAG, "BW raise to" + message.arg1 / 1000 + "kbps"); | |
| 190 | + break; | |
| 191 | + case IStreamer.cnstream_est_bw_drop: | |
| 192 | + Log.i(TAG, "BW drop to" + message.arg1 / 1000 + "kbps"); | |
| 193 | + break; | |
| 194 | + case IStreamer.cnstream_error_start_stream_server: | |
| 195 | + Log.e(TAG, "开始直播是请求服务器失败"); | |
| 196 | + reconnect_msg = "开始直播是请求服务器失败"; | |
| 197 | + break; | |
| 198 | + case IStreamer.cnstream_error_start_stream_network: | |
| 199 | + Log.e(TAG, "开始直播时网络连接失败"); | |
| 200 | + reconnect_msg = "开始直播时网络连接失败"; | |
| 201 | + break; | |
| 202 | + case IStreamer.cnstream_error_start_stream_other: | |
| 203 | + Log.e(TAG, "开始直播活动失败"); | |
| 204 | + reconnect_msg = "开始直播活动失败"; | |
| 205 | + break; | |
| 206 | + case IStreamer.cnstream_error_create_stream_server: | |
| 207 | + Log.e(TAG, "创建直播活动请求服务器失败"); | |
| 208 | + finish_msg = "创建直播活动请求服务器失败"; | |
| 209 | + break; | |
| 210 | + case IStreamer.cnstream_error_create_stream_network: | |
| 211 | + Log.e(TAG, "创建直播活动是网络连接失败"); | |
| 212 | + finish_msg = "创建直播活动是网络连接失败"; | |
| 213 | + break; | |
| 214 | + case IStreamer.cnstream_error_create_stream_other: | |
| 215 | + Log.e(TAG, "创建直播活动时失败"); | |
| 216 | + finish_msg = "创建直播活动时失败"; | |
| 217 | + break; | |
| 218 | + case IStreamer.cnstream_record_error: | |
| 219 | + Log.e(TAG, "直播录制失败"); | |
| 220 | + finish_msg = "直播录制失败"; | |
| 221 | + break; | |
| 222 | + case IStreamer.cnstream_error_stop_stream: | |
| 223 | + Log.e(TAG, "停止直播活动失败"); | |
| 224 | + break; | |
| 225 | + case IStreamer.cnstream_socket_disconnect: | |
| 226 | + Log.e(TAG, "推流socket异常断开"); | |
| 227 | + reconnect_msg = "推流socket异常断开"; | |
| 228 | + break; | |
| 229 | + case IStreamer.cnstream_error_dns_parse_failed: | |
| 230 | + Log.e(TAG, "url域名解析错误"); | |
| 231 | + reconnect_msg = "url域名解析错误"; | |
| 232 | + break; | |
| 233 | + case IStreamer.cnstream_error_connect_failed: | |
| 234 | + Log.e(TAG, "网络连接失败"); | |
| 235 | + reconnect_msg = "网络连接失败"; | |
| 236 | + break; | |
| 237 | + case IStreamer.cnstream_error_connect_breaked: | |
| 238 | + Log.e(TAG, "网络连接断开"); | |
| 239 | + reconnect_msg = "网络连接断开"; | |
| 240 | + break; | |
| 241 | + case IStreamer.cnstream_error_publish_failed: | |
| 242 | + Log.e(TAG, "跟RTMP服务器完成握手后,向{streamname}推流失败)"); | |
| 243 | + reconnect_msg = "跟RTMP服务器完成握手后,向{streamname}推流失败)"; | |
| 244 | + break; | |
| 245 | + case IStreamer.cnstream_error_av_async: | |
| 246 | + Log.e(TAG, "音视频采集pts差值超过5s"); | |
| 247 | + reconnect_msg = "音视频采集pts差值超过5s"; | |
| 248 | + break; | |
| 249 | + case IStreamer.cnstream_video_encoder_error_unsupported: | |
| 250 | + Log.e(TAG, "编码器初始化失败"); | |
| 251 | + reconnect_msg = "编码器初始化失败"; | |
| 252 | + break; | |
| 253 | + case IStreamer.cnstream_video_encoder_error_unknown: | |
| 254 | + Log.e(TAG, "视频编码失败"); | |
| 255 | + reconnect_msg = "视频编码失败"; | |
| 256 | + break; | |
| 257 | + case IStreamer.cnstream_audio_encoder_error_unsupported: | |
| 258 | + Log.e(TAG, "音频初始化失败"); | |
| 259 | + reconnect_msg = "音频初始化失败"; | |
| 260 | + break; | |
| 261 | + case IStreamer.cnstream_audio_encoder_error_unknown: | |
| 262 | + Log.e(TAG, "录音开始失败"); | |
| 263 | + reconnect_msg = "录音开始失败"; | |
| 264 | + break; | |
| 265 | + case IStreamer.cnstream_audio_recorder_error_unknown: | |
| 266 | + finish_msg = "录音开启未知错误"; | |
| 267 | + Log.d(TAG, "录音开启未知错误"); | |
| 268 | + break; | |
| 269 | + case IStreamer.cnstream_camera_error_unknown: | |
| 270 | + Log.d(TAG, "摄像头未知错误"); | |
| 271 | +// finish_msg = "摄像头未知错误"; | |
| 272 | + break; | |
| 273 | + case IStreamer.cnstream_camera_error_start_failed: | |
| 274 | + finish_msg = "打开摄像头失败"; | |
| 275 | + Log.d(TAG, "打开摄像头失败"); | |
| 276 | + break; | |
| 277 | + case IStreamer.cnstream_camera_error_server_died: | |
| 278 | +// finish_msg = "系统camera服务进程退出"; | |
| 279 | + Log.d(TAG, "系统camera服务进程退出"); | |
| 280 | + break; | |
| 281 | + case IStreamer.cnstream_error_already_over: | |
| 282 | + stop_msg = "直播已结束"; | |
| 283 | + Log.d(TAG, "直播已结束"); | |
| 284 | + break; | |
| 285 | + case IStreamer.cnstream_auto_restart_failed: | |
| 286 | + reconnect_msg = "自动重连失败"; | |
| 287 | + Log.d(TAG, "自动重连失败"); | |
| 288 | + break; | |
| 289 | + } | |
| 290 | + if (!TextUtils.isEmpty(reconnect_msg)) { | |
| 291 | + Log.e(TAG, " " + reconnect_msg); | |
| 292 | + } | |
| 293 | + if (!TextUtils.isEmpty(stop_msg)) { | |
| 294 | + Log.e(TAG, " " + stop_msg); | |
| 295 | + } | |
| 296 | + if (!TextUtils.isEmpty(finish_msg)) { | |
| 297 | + Log.e(TAG, " " + finish_msg); | |
| 298 | + } | |
| 299 | + return true; | |
| 300 | + } | |
| 301 | + | |
| 302 | + private IStreamer.OnInfoListener mInfoListener = new IStreamer.OnInfoListener() { | |
| 303 | + @Override | |
| 304 | + public void onInfo(int i, int i1, int i2) { | |
| 305 | + Log.e(TAG, " info " + i); | |
| 306 | + if (mHandler != null) { | |
| 307 | + Message message = new Message(); | |
| 308 | + message.what = i; | |
| 309 | + message.arg1 = i1; | |
| 310 | + message.arg2 = i2; | |
| 311 | + mHandler.sendMessage(message); | |
| 312 | + } | |
| 313 | + } | |
| 314 | + }; | |
| 315 | + | |
| 316 | + private IStreamer.OnErrorListener mErrorListener = new IStreamer.OnErrorListener() { | |
| 317 | + @Override | |
| 318 | + public void onError(int i, int i1, int i2) { | |
| 319 | + Log.e(TAG, " error " + i); | |
| 320 | + if (mHandler != null) { | |
| 321 | + Message message = new Message(); | |
| 322 | + message.what = i; | |
| 323 | + message.arg1 = i1; | |
| 324 | + message.arg2 = i2; | |
| 325 | + mHandler.sendMessage(message); | |
| 326 | + } | |
| 327 | + } | |
| 328 | + }; | |
| 329 | + | |
| 330 | + private Dialog dialog; | |
| 331 | + | |
| 332 | + private void startCameraPreviewWithPermCheck() { | |
| 333 | + int cameraPerm = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA); | |
| 334 | + int audioPerm = ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO); | |
| 335 | + if (cameraPerm != PackageManager.PERMISSION_GRANTED || audioPerm != PackageManager.PERMISSION_GRANTED) { | |
| 336 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { | |
| 337 | + if (dialog != null) dialog.dismiss(); | |
| 338 | + dialog = new AlertDialog.Builder(this) | |
| 339 | + .setMessage("") | |
| 340 | + .setPositiveButton("去设置", new DialogInterface.OnClickListener() { | |
| 341 | + @Override | |
| 342 | + public void onClick(DialogInterface dialogInterface, int i) { | |
| 343 | + Intent intent = new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS); | |
| 344 | + startActivity(intent); | |
| 345 | + } | |
| 346 | + }) | |
| 347 | + .setNegativeButton("取消", new DialogInterface.OnClickListener() { | |
| 348 | + @Override | |
| 349 | + public void onClick(DialogInterface dialogInterface, int i) { | |
| 350 | + dialog.dismiss(); | |
| 351 | + } | |
| 352 | + }).show(); | |
| 353 | + } else { | |
| 354 | + String[] permissions = {Manifest.permission.CAMERA, | |
| 355 | + Manifest.permission.RECORD_AUDIO, | |
| 356 | + Manifest.permission.READ_EXTERNAL_STORAGE}; | |
| 357 | + ActivityCompat.requestPermissions(this, permissions, | |
| 358 | + PERMISSION_REQUEST_CAMERA_AUDIOREC); | |
| 359 | + } | |
| 360 | + } else { | |
| 361 | + mStreamer.startCameraPreview(); | |
| 362 | + } | |
| 363 | + } | |
| 364 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/ui/activity/StreamActivity.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.ui.activity; | |
| 2 | + | |
| 3 | +import android.app.AlertDialog; | |
| 4 | +import android.app.Dialog; | |
| 5 | +import android.content.DialogInterface; | |
| 6 | +import android.databinding.DataBindingUtil; | |
| 7 | +import android.os.Bundle; | |
| 8 | +import android.os.Handler; | |
| 9 | +import android.os.Message; | |
| 10 | +import android.support.v7.widget.LinearLayoutManager; | |
| 11 | +import android.text.Spannable; | |
| 12 | +import android.text.SpannableStringBuilder; | |
| 13 | +import android.text.TextUtils; | |
| 14 | +import android.text.style.ForegroundColorSpan; | |
| 15 | +import android.view.View; | |
| 16 | +import android.view.Window; | |
| 17 | +import android.view.WindowManager; | |
| 18 | +import android.widget.TextView; | |
| 19 | + | |
| 20 | +import com.cnlive.gundam.R; | |
| 21 | +import com.cnlive.gundam.databinding.ActivityStreamPortraitBinding; | |
| 22 | +import com.cnlive.gundam.stream.model.ChatItem; | |
| 23 | +import com.cnlive.gundam.stream.model.ExtensionModel; | |
| 24 | +import com.cnlive.gundam.stream.model.ShowView; | |
| 25 | +import com.cnlive.gundam.stream.ui.adapter.SimpleAdapter; | |
| 26 | +import com.cnlive.gundam.stream.util.ChatConnect; | |
| 27 | +import com.cnlive.gundam.stream.util.TimerUtil; | |
| 28 | +import com.cnlive.libs.stream.base.IStreamer; | |
| 29 | +import com.cnlive.libs.stream.model.ActivityConfig; | |
| 30 | +import com.cnlive.libs.stream.model.Filters; | |
| 31 | +import com.cnlive.libs.util.chat.ChatUtil; | |
| 32 | +import com.cnlive.libs.util.chat.base.IChat; | |
| 33 | +import com.cnlive.libs.util.chat.model.CNChatRoomInfo; | |
| 34 | +import com.cnlive.libs.util.chat.model.CNMessage; | |
| 35 | +import com.cnlive.libs.util.chat.model.CNUserInfo; | |
| 36 | +import com.google.gson.Gson; | |
| 37 | + | |
| 38 | +import org.json.JSONException; | |
| 39 | +import org.json.JSONObject; | |
| 40 | + | |
| 41 | +import java.util.ArrayList; | |
| 42 | +import java.util.List; | |
| 43 | + | |
| 44 | +public class StreamActivity extends BaseStreamActivity implements ChatConnect.ChatCallback, TimerUtil.TimerListener { | |
| 45 | + | |
| 46 | + private boolean isFace = false; | |
| 47 | + private boolean isFlash = false; | |
| 48 | + | |
| 49 | + private boolean inLive = false; | |
| 50 | + | |
| 51 | + private boolean hasError = false; | |
| 52 | + | |
| 53 | + private String activityId; | |
| 54 | + private String channelId; | |
| 55 | + private String channelName; | |
| 56 | + private String coverImgUrl; | |
| 57 | + private boolean isLandscape = false; | |
| 58 | + | |
| 59 | + private Dialog endDialog; | |
| 60 | + private ActivityStreamPortraitBinding binding; | |
| 61 | + | |
| 62 | + private String roomId; | |
| 63 | + | |
| 64 | + private ShowView showView = new ShowView(); | |
| 65 | + | |
| 66 | + private List<ChatItem> chatItemList; | |
| 67 | + private SimpleAdapter chatAdapter; | |
| 68 | + private ChatConnect chatConnect; | |
| 69 | + | |
| 70 | + private TimerUtil timerUtil; | |
| 71 | + private String extensions; | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + protected void onCreate(Bundle savedInstanceState) { | |
| 75 | + super.onCreate(savedInstanceState); | |
| 76 | + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); | |
| 77 | + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); | |
| 78 | + requestWindowFeature(Window.FEATURE_NO_TITLE); | |
| 79 | + | |
| 80 | + //// TODO: 5/22/2017 统计 | |
| 81 | + initData(); | |
| 82 | + | |
| 83 | + binding = DataBindingUtil.setContentView(this, R.layout.activity_stream_portrait); | |
| 84 | + initStreamer(isLandscape, binding.cameraPreview); | |
| 85 | + showView.setStartBtn(true); | |
| 86 | + showView.setRetryLayout(false); | |
| 87 | + showView.setEndLayout(false); | |
| 88 | + showView.setMsgHint(false); | |
| 89 | + showView.setAutoRecMsg(false); | |
| 90 | + showView.setChatView(false); | |
| 91 | + showView.setViewers(false); | |
| 92 | + binding.setIsShow(showView); | |
| 93 | + binding.chatRecyclerView.setLayoutManager(new LinearLayoutManager(this)); | |
| 94 | + chatItemList = new ArrayList<>(); | |
| 95 | + | |
| 96 | + timerUtil = new TimerUtil(this); | |
| 97 | + } | |
| 98 | + | |
| 99 | + private void initData() { | |
| 100 | + activityId = getIntent().getStringExtra("activityId"); | |
| 101 | + channelId = getIntent().getStringExtra("channelId"); | |
| 102 | + channelName = getIntent().getStringExtra("channelName"); | |
| 103 | + coverImgUrl = getIntent().getStringExtra("coverImgUrl"); | |
| 104 | + isLandscape = getIntent().getBooleanExtra("landscape", false); | |
| 105 | + | |
| 106 | + ExtensionModel extensionModel = new ExtensionModel(channelName, coverImgUrl); | |
| 107 | + extensions = new Gson().toJson(extensionModel); | |
| 108 | + | |
| 109 | + roomId = activityId; | |
| 110 | + } | |
| 111 | + | |
| 112 | + public void onClick(View view) { | |
| 113 | + if (view.getId() == R.id.btn_beautiful) { | |
| 114 | + isFace = !isFace; | |
| 115 | + setFilter(isFace ? Filters.DENOISE : Filters.BEAUTY_DISABLE); | |
| 116 | + toggleBeautifulBtn(isFace); | |
| 117 | + } else if (view.getId() == R.id.btn_flip) { | |
| 118 | + toggleFlashBtn(isFrontCamera()); | |
| 119 | + toggleTorch(isFlash = false); | |
| 120 | + switchCamera(); | |
| 121 | + } else if (view.getId() == R.id.btn_flash) { | |
| 122 | + toggleTorch(isFlash = !isFlash); | |
| 123 | + } else if (view.getId() == R.id.btn_close) { | |
| 124 | + onBackPressed(); | |
| 125 | + } else if (view.getId() == R.id.startStream) { | |
| 126 | + startStream(activityConfig); | |
| 127 | + showView.setStartBtn(false); | |
| 128 | + binding.setIsShow(showView); | |
| 129 | + } else if (view.getId() == R.id.btn_end_close) { | |
| 130 | + finish(); | |
| 131 | + } else if (view.getId() == R.id.button_retry) { | |
| 132 | + startStream(activityConfig); | |
| 133 | + showRetryLayout(false); | |
| 134 | + } | |
| 135 | + } | |
| 136 | + | |
| 137 | + @Override | |
| 138 | + public boolean handleMessage(Message message) { | |
| 139 | + super.handleMessage(message); | |
| 140 | + | |
| 141 | + switch (message.what) { | |
| 142 | + case IStreamer.cnstream_camera_init_done: | |
| 143 | + isFace = true; | |
| 144 | + setFilter(Filters.DENOISE); | |
| 145 | + toggleBeautifulBtn(true); | |
| 146 | + break; | |
| 147 | + case IStreamer.cnstream_open_stream_succ: | |
| 148 | + inLive = true; | |
| 149 | + if (showView.isRetryLayout()) | |
| 150 | + showRetryLayout(false); | |
| 151 | + //// TODO: 5/23/2017 连接聊天室 | |
| 152 | + new Handler().post(new Runnable() { | |
| 153 | + @Override | |
| 154 | + public void run() { | |
| 155 | + if (!hasError) { | |
| 156 | + chatConnect = new ChatConnect(StreamActivity.this, StreamActivity.this); | |
| 157 | + chatConnect.connect(roomId, new CNUserInfo(channelId, channelName, coverImgUrl)); | |
| 158 | + showView.setViewers(true); | |
| 159 | + } | |
| 160 | + chatViewShow(true); | |
| 161 | + } | |
| 162 | + }); | |
| 163 | + | |
| 164 | + break; | |
| 165 | + } | |
| 166 | + | |
| 167 | + if (!TextUtils.isEmpty(reconnect_msg)) { | |
| 168 | + hasError = true; | |
| 169 | + showRetryView(); | |
| 170 | + } | |
| 171 | + if (!TextUtils.isEmpty(finish_msg)) { | |
| 172 | + if (isRecording()) { | |
| 173 | + stopRecord(finish_msg); | |
| 174 | + } else { | |
| 175 | + finish(); | |
| 176 | + } | |
| 177 | + } | |
| 178 | + if (!TextUtils.isEmpty(stop_msg)) { | |
| 179 | + stopRecord(stop_msg); | |
| 180 | + showMsgHint(true); | |
| 181 | + } | |
| 182 | + return true; | |
| 183 | + } | |
| 184 | + | |
| 185 | + private void stopRecord(String msg) { | |
| 186 | + stopStream(); | |
| 187 | + showEndView(msg); | |
| 188 | + } | |
| 189 | + | |
| 190 | + //重试页面 | |
| 191 | + private void showRetryView() { | |
| 192 | + if (showView.isChatView()) { | |
| 193 | + chatViewShow(false); | |
| 194 | + } | |
| 195 | + if (autoRestart()) { | |
| 196 | + showAutoRecMsg(true); | |
| 197 | + toggleAutoRecMsg(reconnect_msg); | |
| 198 | + } else { | |
| 199 | + showAutoRecMsg(false); | |
| 200 | + } | |
| 201 | + showRetryLayout(true); | |
| 202 | + } | |
| 203 | + | |
| 204 | + //结束页面 | |
| 205 | + private void showEndView(String msg) { | |
| 206 | + if (showView.isRetryLayout()) { | |
| 207 | + showRetryLayout(false); | |
| 208 | + } | |
| 209 | + showView.setViewers(false); | |
| 210 | + if (msg.equals("直播已结束")) { | |
| 211 | + showMsgHint(true); | |
| 212 | + } else { | |
| 213 | + showMsgHint(false); | |
| 214 | + } | |
| 215 | + inLive = false; | |
| 216 | + showView.setRecordBtns(false); | |
| 217 | + | |
| 218 | + getOnlinePerson(); | |
| 219 | + | |
| 220 | + binding.setIsShow(showView); | |
| 221 | + chatViewShow(false); | |
| 222 | + showEndLayout(true); | |
| 223 | + } | |
| 224 | + | |
| 225 | + private void showSpannableView(TextView view, String content, int start, int end) { | |
| 226 | + SpannableStringBuilder mSpannableStringBuilder = new SpannableStringBuilder(content); | |
| 227 | + mSpannableStringBuilder.setSpan | |
| 228 | + (new ForegroundColorSpan(0xFFfbdb44), start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); | |
| 229 | + view.setText(mSpannableStringBuilder); | |
| 230 | + } | |
| 231 | + | |
| 232 | + private void showDialog() { | |
| 233 | + endDialog = new AlertDialog.Builder(this).setMessage("确认结束此直播吗?") | |
| 234 | + .setPositiveButton("确认", new DialogInterface.OnClickListener() { | |
| 235 | + @Override | |
| 236 | + public void onClick(DialogInterface dialogInterface, int i) { | |
| 237 | + endDialog.dismiss(); | |
| 238 | + stopRecord(""); | |
| 239 | + } | |
| 240 | + }) | |
| 241 | + .setNegativeButton("取消", new DialogInterface.OnClickListener() { | |
| 242 | + @Override | |
| 243 | + public void onClick(DialogInterface dialogInterface, int i) { | |
| 244 | + endDialog.dismiss(); | |
| 245 | + } | |
| 246 | + }).show(); | |
| 247 | + } | |
| 248 | + | |
| 249 | + private ActivityConfig activityConfig = new ActivityConfig() { | |
| 250 | + @Override | |
| 251 | + public String getActivityID() { | |
| 252 | + return activityId; | |
| 253 | + } | |
| 254 | + | |
| 255 | + @Override | |
| 256 | + public String getActivityName() { | |
| 257 | + return null; | |
| 258 | + } | |
| 259 | + | |
| 260 | + @Override | |
| 261 | + public int getActivityStatus() { | |
| 262 | + return 0; | |
| 263 | + } | |
| 264 | + | |
| 265 | + @Override | |
| 266 | + public int getIsHorizontalScreen() { | |
| 267 | + return isLandscape ? 1 : 0; | |
| 268 | + } | |
| 269 | + | |
| 270 | + @Override | |
| 271 | + public String getChannelID() { | |
| 272 | + return channelId; | |
| 273 | + } | |
| 274 | + | |
| 275 | + @Override | |
| 276 | + public String getCoverImgUrl() { | |
| 277 | + return coverImgUrl; | |
| 278 | + } | |
| 279 | + | |
| 280 | + @Override | |
| 281 | + public String getActivityCategory() { | |
| 282 | + return null; | |
| 283 | + } | |
| 284 | + | |
| 285 | + @Override | |
| 286 | + public String getExtensions() { | |
| 287 | + return extensions; | |
| 288 | + } | |
| 289 | + | |
| 290 | + @Override | |
| 291 | + public String getUuid() { | |
| 292 | + return null; | |
| 293 | + } | |
| 294 | + | |
| 295 | + @Override | |
| 296 | + public String getCallbackAcitvityStatushttpPostUrl() { | |
| 297 | + return null; | |
| 298 | + } | |
| 299 | + }; | |
| 300 | + | |
| 301 | + @Override | |
| 302 | + protected void onPause() { | |
| 303 | + super.onPause(); | |
| 304 | + if (endDialog != null) endDialog.dismiss(); | |
| 305 | + if (timerUtil != null) timerUtil.cancelTimer(); | |
| 306 | + } | |
| 307 | + | |
| 308 | + @Override | |
| 309 | + protected void onResume() { | |
| 310 | + super.onResume(); | |
| 311 | + if (timerUtil != null) timerUtil.startTimer(0, TimerUtil.UPDATE_ONLINE_PERSON); | |
| 312 | + } | |
| 313 | + | |
| 314 | + @Override | |
| 315 | + protected void onDestroy() { | |
| 316 | + super.onDestroy(); | |
| 317 | + if (chatConnect != null) chatConnect.disconnect(); | |
| 318 | + } | |
| 319 | + | |
| 320 | + @Override | |
| 321 | + public void onBackPressed() { | |
| 322 | + if (!inLive) { | |
| 323 | + super.onBackPressed(); | |
| 324 | + } else { | |
| 325 | + showDialog(); | |
| 326 | + } | |
| 327 | + } | |
| 328 | + | |
| 329 | + private void showRetryLayout(boolean show) { | |
| 330 | + showView.setRetryLayout(show); | |
| 331 | + binding.setIsShow(showView); | |
| 332 | + } | |
| 333 | + | |
| 334 | + private void showEndLayout(boolean show) { | |
| 335 | + showView.setEndLayout(show); | |
| 336 | + binding.setIsShow(showView); | |
| 337 | + } | |
| 338 | + | |
| 339 | + private void showMsgHint(boolean show) { | |
| 340 | + showView.setMsgHint(show); | |
| 341 | + binding.setIsShow(showView); | |
| 342 | + } | |
| 343 | + | |
| 344 | + private void showAutoRecMsg(boolean show) { | |
| 345 | + showView.setAutoRecMsg(show); | |
| 346 | + binding.setIsShow(showView); | |
| 347 | + } | |
| 348 | + | |
| 349 | + private void toggleAutoRecMsg(String msg) { | |
| 350 | + if (msg.equals("自动重连失败")) { | |
| 351 | + showView.setAutoRectTxt(false); | |
| 352 | + } else { | |
| 353 | + if (getAutoRestartCount() > 0) { | |
| 354 | + showView.setAutoRectTxt(true); | |
| 355 | + } else { | |
| 356 | + showAutoRecMsg(false); | |
| 357 | + } | |
| 358 | + } | |
| 359 | + binding.setIsShow(showView); | |
| 360 | + } | |
| 361 | + | |
| 362 | + private void toggleBeautifulBtn(boolean beauty) { | |
| 363 | + showView.setBeautifulBtn(beauty); | |
| 364 | + binding.setIsShow(showView); | |
| 365 | + } | |
| 366 | + | |
| 367 | + private void toggleFlashBtn(boolean isFlash) { | |
| 368 | + showView.setFlashBtn(isFlash); | |
| 369 | + binding.setIsShow(showView); | |
| 370 | + } | |
| 371 | + | |
| 372 | + private void chatViewShow(boolean show) { | |
| 373 | + showView.setChatView(show); | |
| 374 | + binding.setIsShow(showView); | |
| 375 | + } | |
| 376 | + | |
| 377 | + //聊天室 | |
| 378 | + @Override | |
| 379 | + public void onChatState(int what) { | |
| 380 | + | |
| 381 | + } | |
| 382 | + | |
| 383 | + @Override | |
| 384 | + public void onChatMessage(CNMessage cnMessage) { | |
| 385 | + //// TODO: 5/23/2017 Recyclerview添加数据 | |
| 386 | + String headUrl = cnMessage.getUserInfo().getHeadUrl() == null ? "" : cnMessage.getUserInfo().getHeadUrl(); | |
| 387 | + String userName = cnMessage.getUserInfo().getUserName() == null ? "" : cnMessage.getUserInfo().getUserName(); | |
| 388 | + String content = null; | |
| 389 | + try { | |
| 390 | + content = cnMessage.getContent() == null ? "" : (String) new JSONObject(cnMessage.getContent()).get("message"); | |
| 391 | + } catch (JSONException e) { | |
| 392 | + e.printStackTrace(); | |
| 393 | + } | |
| 394 | + ChatItem chatItem = new ChatItem(headUrl, userName, content); | |
| 395 | + chatItemList.add(chatItem); | |
| 396 | + chatAdapter = new SimpleAdapter(this, chatItemList, R.layout.item_chat, com.cnlive.gundam.BR.chat); | |
| 397 | + binding.setChatAdapter(chatAdapter); | |
| 398 | + | |
| 399 | + } | |
| 400 | + | |
| 401 | + private void getOnlinePerson() { | |
| 402 | + ChatUtil.getChatRoomInfo(roomId, 0, CNChatRoomInfo.ChatRoomMemberOrder.RC_CHAT_ROOM_MEMBER_ASC, new IChat.CNResultCallback<CNChatRoomInfo>() { | |
| 403 | + @Override | |
| 404 | + public void onSuccess(CNChatRoomInfo cnChatRoomInfo) { | |
| 405 | + binding.viewers.setText(cnChatRoomInfo.getTotalMemberCount() + "人"); | |
| 406 | + } | |
| 407 | + | |
| 408 | + @Override | |
| 409 | + public void onError(int i, String s) { | |
| 410 | + } | |
| 411 | + }); | |
| 412 | + } | |
| 413 | + | |
| 414 | + @Override | |
| 415 | + public void onTimer() { | |
| 416 | + getOnlinePerson(); | |
| 417 | + } | |
| 418 | +} | |
| 419 | + | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/ui/adapter/ChatAdapter.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.ui.adapter; | |
| 2 | + | |
| 3 | + | |
| 4 | +import android.content.Context; | |
| 5 | +import android.databinding.DataBindingUtil; | |
| 6 | +import android.databinding.ViewDataBinding; | |
| 7 | +import android.view.LayoutInflater; | |
| 8 | +import android.view.View; | |
| 9 | +import android.view.ViewGroup; | |
| 10 | +import android.widget.BaseAdapter; | |
| 11 | + | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * Created by Lynn on 5/24/2017. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +public class ChatAdapter<T> extends BaseAdapter { | |
| 19 | + private Context mContext; | |
| 20 | + private List<T> mList; | |
| 21 | + private int layoutId; | |
| 22 | + private int variableId; | |
| 23 | + | |
| 24 | + public ChatAdapter(Context mContext, List<T> list, int layoutId, int variableId) { | |
| 25 | + this.mContext = mContext; | |
| 26 | + this.mList = list; | |
| 27 | + this.layoutId = layoutId; | |
| 28 | + this.variableId = variableId; | |
| 29 | + } | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public int getCount() { | |
| 33 | + return mList.size(); | |
| 34 | + } | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public Object getItem(int i) { | |
| 38 | + return mList.get(i); | |
| 39 | + } | |
| 40 | + | |
| 41 | + @Override | |
| 42 | + public long getItemId(int i) { | |
| 43 | + return i; | |
| 44 | + } | |
| 45 | + | |
| 46 | + @Override | |
| 47 | + public View getView(int i, View view, ViewGroup viewGroup) { | |
| 48 | + ViewDataBinding binding; | |
| 49 | + if (view == null) { | |
| 50 | + binding = DataBindingUtil.inflate(LayoutInflater.from(mContext), layoutId, viewGroup, false); | |
| 51 | + } else { | |
| 52 | + binding = DataBindingUtil.getBinding(view); | |
| 53 | + } | |
| 54 | + binding.setVariable(variableId, mList.get(i)); | |
| 55 | + binding.executePendingBindings(); | |
| 56 | + return binding.getRoot(); | |
| 57 | + } | |
| 58 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/ui/adapter/SimpleAdapter.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.ui.adapter; | |
| 2 | + | |
| 3 | +import android.content.Context; | |
| 4 | +import android.databinding.DataBindingUtil; | |
| 5 | +import android.databinding.ViewDataBinding; | |
| 6 | +import android.support.v7.widget.RecyclerView; | |
| 7 | +import android.view.LayoutInflater; | |
| 8 | +import android.view.View; | |
| 9 | +import android.view.ViewGroup; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * Created by Lynn on 5/25/2017. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +public class SimpleAdapter<T> extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> { | |
| 18 | + private Context mContext; | |
| 19 | + private List<T> activeInfoList; | |
| 20 | + private int layoutId; | |
| 21 | + private int variableId; | |
| 22 | + | |
| 23 | + | |
| 24 | + public SimpleAdapter(Context mContext, List<T> activeInfoList, int layoutId, int variableId) { | |
| 25 | + this.mContext = mContext; | |
| 26 | + this.activeInfoList = activeInfoList; | |
| 27 | + this.layoutId = layoutId; | |
| 28 | + this.variableId = variableId; | |
| 29 | + } | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
| 33 | + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); | |
| 34 | + ViewDataBinding binding = DataBindingUtil.inflate(inflater, layoutId, parent, false); | |
| 35 | + ViewHolder viewHolder = new ViewHolder(binding.getRoot()); | |
| 36 | + viewHolder.setBinding(binding); | |
| 37 | + return viewHolder; | |
| 38 | + } | |
| 39 | + | |
| 40 | + @Override | |
| 41 | + public void onBindViewHolder(SimpleAdapter.ViewHolder holder, int position) { | |
| 42 | + holder.getBinding().setVariable(variableId, activeInfoList.get(position)); | |
| 43 | + holder.getBinding().executePendingBindings(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + | |
| 47 | + @Override | |
| 48 | + public long getItemId(int i) { | |
| 49 | + return i; | |
| 50 | + } | |
| 51 | + | |
| 52 | + @Override | |
| 53 | + public int getItemCount() { | |
| 54 | + return activeInfoList == null ? 0 : activeInfoList.size(); | |
| 55 | + } | |
| 56 | + | |
| 57 | + public class ViewHolder extends RecyclerView.ViewHolder { | |
| 58 | + | |
| 59 | + private ViewDataBinding binding; | |
| 60 | + | |
| 61 | + public ViewDataBinding getBinding() { | |
| 62 | + return binding; | |
| 63 | + } | |
| 64 | + | |
| 65 | + public void setBinding(ViewDataBinding binding) { | |
| 66 | + this.binding = binding; | |
| 67 | + } | |
| 68 | + | |
| 69 | + public ViewHolder(View itemView) { | |
| 70 | + super(itemView); | |
| 71 | + } | |
| 72 | + } | |
| 73 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/util/ChatConnect.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.util; | |
| 2 | + | |
| 3 | +import android.content.Context; | |
| 4 | +import android.util.Log; | |
| 5 | + | |
| 6 | +import com.cnlive.libs.util.chat.ChatUtil; | |
| 7 | +import com.cnlive.libs.util.chat.base.IChat; | |
| 8 | +import com.cnlive.libs.util.chat.model.CNChatRoomInfo; | |
| 9 | +import com.cnlive.libs.util.chat.model.CNMessage; | |
| 10 | +import com.cnlive.libs.util.chat.model.CNUserInfo; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * Created by Lynn on 5/23/2017. | |
| 14 | + */ | |
| 15 | + | |
| 16 | +public class ChatConnect implements IChat.OnConnectStatusListener, IChat.OnReceiveMessageListener { | |
| 17 | + private static final String TAG = "ChatConnect"; | |
| 18 | + | |
| 19 | + public static final int ERROR_CONNECT = 1001; | |
| 20 | + public static final int ERROR_CHAT = 1002; | |
| 21 | + public static final int ERROR_DISCONNECT = 1003; | |
| 22 | + | |
| 23 | + public static final int STATE_CONNECT = 2001; | |
| 24 | + public static final int STATE_JOIN = 2002; | |
| 25 | + public static final int STATE_DISCONNECT = 2003; | |
| 26 | + public static final int STATE_CONNECTING = 2004; | |
| 27 | + | |
| 28 | + private String userId; | |
| 29 | + private String userName; | |
| 30 | + private String headUrl; | |
| 31 | + | |
| 32 | + private String mRoomId; | |
| 33 | + private Context mContext; | |
| 34 | + private ChatCallback callback; | |
| 35 | + private CNChatRoomInfo mCnChatRoomInfo; | |
| 36 | + | |
| 37 | + public ChatConnect(Context mContext, ChatCallback callback) { | |
| 38 | + this.mContext = mContext; | |
| 39 | + this.callback = callback; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void connect(final String roomId, CNUserInfo cnUserInfo) { | |
| 43 | + userId = cnUserInfo.getUserId(); | |
| 44 | + userName = cnUserInfo.getUserName(); | |
| 45 | + headUrl = cnUserInfo.getHeadUrl(); | |
| 46 | + | |
| 47 | + Log.e(TAG, userId + " : " + userName + " : " + headUrl); | |
| 48 | + this.mRoomId = roomId; | |
| 49 | + | |
| 50 | + ChatUtil.setOnReceiveMessageListener(this); | |
| 51 | +// ChatUtil.setConnectStatusListener(this); | |
| 52 | + ChatUtil.setOnConnectStatusListener(this); | |
| 53 | + | |
| 54 | + IChat.OnConnectListener onConnectListener = new IChat.OnConnectListener() { | |
| 55 | + @Override | |
| 56 | + public void onTokenIncorrect(String s) { | |
| 57 | + if (callback != null) callback.onChatState(ERROR_CONNECT); | |
| 58 | + } | |
| 59 | + | |
| 60 | + @Override | |
| 61 | + public void onSuccess(String s) { | |
| 62 | + if (callback != null) callback.onChatState(STATE_CONNECT); | |
| 63 | + if (userId == null || userId == "") ChatUtil.modifyUser(userName, ""); | |
| 64 | + ChatUtil.joinChatRoom(mRoomId, 0, new IChat.OnOperationListener() { | |
| 65 | + @Override | |
| 66 | + public void onSuccess(int i, String s) { | |
| 67 | + if (callback != null) callback.onChatState(STATE_JOIN); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public void onError(int i, String s) { | |
| 72 | + if (callback != null) callback.onChatState(ERROR_CHAT); | |
| 73 | + } | |
| 74 | + }); | |
| 75 | + } | |
| 76 | + | |
| 77 | + @Override | |
| 78 | + public void onError(int i, String s) { | |
| 79 | + if (callback != null) callback.onChatState(ERROR_CONNECT); | |
| 80 | + } | |
| 81 | + }; | |
| 82 | + | |
| 83 | + if (userId != null || userId != "") { | |
| 84 | + ChatUtil.connect(new CNUserInfo(String.valueOf(userId), userName, headUrl), onConnectListener); | |
| 85 | + } else { | |
| 86 | + ChatUtil.connect(onConnectListener); | |
| 87 | + } | |
| 88 | + } | |
| 89 | + | |
| 90 | + int viewCount = 0; | |
| 91 | + | |
| 92 | + public int getChatRoomInfo() { | |
| 93 | + ChatUtil.getChatRoomInfo(mRoomId, 500, CNChatRoomInfo.ChatRoomMemberOrder.RC_CHAT_ROOM_MEMBER_ASC, new IChat.CNResultCallback<CNChatRoomInfo>() { | |
| 94 | + @Override | |
| 95 | + public void onSuccess(CNChatRoomInfo cnChatRoomInfo) { | |
| 96 | + mCnChatRoomInfo = cnChatRoomInfo; | |
| 97 | + viewCount = cnChatRoomInfo.getTotalMemberCount(); | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public void onError(int i, String s) { | |
| 102 | + } | |
| 103 | + }); | |
| 104 | + return viewCount; | |
| 105 | + } | |
| 106 | + | |
| 107 | + public void disconnect() { | |
| 108 | + ChatUtil.quitChatRoom(mRoomId, new IChat.OnOperationListener() { | |
| 109 | + @Override | |
| 110 | + public void onSuccess(int i, String s) { | |
| 111 | + } | |
| 112 | + | |
| 113 | + @Override | |
| 114 | + public void onError(int i, String s) { | |
| 115 | + if (callback != null) callback.onChatState(ERROR_DISCONNECT); | |
| 116 | + } | |
| 117 | + }); | |
| 118 | + ChatUtil.removeReceiveMessageListener(this); | |
| 119 | + ChatUtil.removeConnectStatusListener(this); | |
| 120 | + callback = null; | |
| 121 | + mContext = null; | |
| 122 | + } | |
| 123 | + | |
| 124 | + @Override | |
| 125 | + public void onConnectStatus(int i, String s) { | |
| 126 | + switch (i) { | |
| 127 | + case IChat.CONNECTED: | |
| 128 | + if (callback != null) callback.onChatState(STATE_CONNECT); | |
| 129 | + break; | |
| 130 | + case IChat.CONNECTING: | |
| 131 | + if (callback != null) callback.onChatState(STATE_CONNECTING); | |
| 132 | + break; | |
| 133 | + case IChat.DISCONNECTED: | |
| 134 | + case IChat.NETWORK_UNAVAILABLE: | |
| 135 | + if (callback != null) callback.onChatState(STATE_DISCONNECT); | |
| 136 | + break; | |
| 137 | + } | |
| 138 | + | |
| 139 | + } | |
| 140 | + | |
| 141 | + @Override | |
| 142 | + public void processMessage(CNMessage cnMessage) { | |
| 143 | + | |
| 144 | + if (mRoomId.equals(cnMessage.getTargetId())) { | |
| 145 | +// String from = cnMessage.getUserInfo() == null ? "" : cnMessage.getUserInfo().getUserName(); | |
| 146 | +// String body = cnMessage.getContent(); | |
| 147 | +// String userId = ChatUtil.getCurrentUserInfo().getUserId(); | |
| 148 | + if (callback != null) callback.onChatMessage(cnMessage); | |
| 149 | + } | |
| 150 | + | |
| 151 | + } | |
| 152 | + | |
| 153 | + public void setCallback(ChatCallback callback) { | |
| 154 | + this.callback = callback; | |
| 155 | + } | |
| 156 | + | |
| 157 | + public interface ChatCallback { | |
| 158 | + void onChatState(int what); | |
| 159 | + | |
| 160 | + void onChatMessage(CNMessage cnMessage); | |
| 161 | + } | |
| 162 | +} | ... | ... |
app/src/main/java/com/cnlive/gundam/stream/util/TimerUtil.java
0 → 100644
| 1 | +package com.cnlive.gundam.stream.util; | |
| 2 | + | |
| 3 | +import android.os.Handler; | |
| 4 | +import android.os.Message; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * Created by Lynn on 5/25/2017. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +public class TimerUtil { | |
| 11 | + | |
| 12 | + public static final int UPDATE_ONLINE_PERSON = 30000; | |
| 13 | + | |
| 14 | + private final int HANDLER_WHAT = 1; | |
| 15 | + private int delayTime; | |
| 16 | + | |
| 17 | + private TimerHandler mHandler = null; | |
| 18 | + private TimerListener l; | |
| 19 | + | |
| 20 | + public TimerUtil(TimerListener listener) { | |
| 21 | + if (mHandler == null) | |
| 22 | + mHandler = new TimerHandler(); | |
| 23 | + this.l = listener; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void startTimer(int startTime, int delay) { | |
| 27 | + delayTime = delay; | |
| 28 | + if (mHandler != null) { | |
| 29 | + mHandler.removeMessages(HANDLER_WHAT); | |
| 30 | + } else { | |
| 31 | + mHandler = new TimerHandler(); | |
| 32 | + } | |
| 33 | + mHandler.sendEmptyMessageDelayed(HANDLER_WHAT, startTime); | |
| 34 | + } | |
| 35 | + | |
| 36 | + public void cancelTimer() { | |
| 37 | + if (mHandler != null && mHandler.hasMessages(HANDLER_WHAT)) { | |
| 38 | + mHandler.removeMessages(HANDLER_WHAT); | |
| 39 | + mHandler = null; | |
| 40 | + } | |
| 41 | + } | |
| 42 | + | |
| 43 | + class TimerHandler extends Handler { | |
| 44 | + @Override | |
| 45 | + public void handleMessage(Message msg) { | |
| 46 | + super.handleMessage(msg); | |
| 47 | + if (msg.what == HANDLER_WHAT) { | |
| 48 | + startTimer(delayTime, delayTime); | |
| 49 | + if (l != null) l.onTimer(); | |
| 50 | + } | |
| 51 | + } | |
| 52 | + } | |
| 53 | + | |
| 54 | + public interface TimerListener { | |
| 55 | + void onTimer(); | |
| 56 | + } | |
| 57 | + | |
| 58 | +} | ... | ... |
app/src/main/jniLibs/arm64-v8a/libRongIMLib.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/arm64-v8a/libksylive.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libRongIMLib.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi-v7a/libksylive.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi/libRongIMLib.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/armeabi/libksylive.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/x86/libRongIMLib.so
0 → 100644
No preview for this file type
app/src/main/jniLibs/x86/libksylive.so
0 → 100644
No preview for this file type
app/src/main/res/drawable-hdpi/ic_bubble.png
0 → 100644
4.46 KB
app/src/main/res/drawable-hdpi/ic_bubble_sel.png
0 → 100644
4.12 KB
app/src/main/res/drawable-hdpi/ic_close.png
0 → 100644
4.45 KB
app/src/main/res/drawable-hdpi/ic_close_on.png
0 → 100644
4.12 KB
app/src/main/res/drawable-hdpi/ic_flash_on.png
0 → 100644
4.11 KB
app/src/main/res/drawable-hdpi/ic_flash_on_sel.png
0 → 100644
3.91 KB
app/src/main/res/drawable-hdpi/ic_switch_camera.png
0 → 100644
4.15 KB
app/src/main/res/drawable-hdpi/ic_switch_camera_sel.png
0 → 100644
4.05 KB
app/src/main/res/drawable-mdpi/ic_bubble.png
0 → 100644
2.49 KB
app/src/main/res/drawable-mdpi/ic_bubble_sel.png
0 → 100644
2.29 KB
app/src/main/res/drawable-mdpi/ic_close.png
0 → 100644
2.43 KB
app/src/main/res/drawable-mdpi/ic_close_on.png
0 → 100644
2.25 KB
app/src/main/res/drawable-mdpi/ic_flash_on.png
0 → 100644
2.28 KB
app/src/main/res/drawable-mdpi/ic_flash_on_sel.png
0 → 100644
2.21 KB
app/src/main/res/drawable-mdpi/ic_switch_camera.png
0 → 100644
2.36 KB
app/src/main/res/drawable-mdpi/ic_switch_camera_sel.png
0 → 100644
2.26 KB
app/src/main/res/drawable-xhdpi/ic_bubble.png
0 → 100644
5.84 KB
app/src/main/res/drawable-xhdpi/ic_bubble_sel.png
0 → 100644
5.52 KB
app/src/main/res/drawable-xhdpi/ic_close.png
0 → 100644
5.83 KB
app/src/main/res/drawable-xhdpi/ic_close_on.png
0 → 100644
5.44 KB
app/src/main/res/drawable-xhdpi/ic_flash_on.png
0 → 100644
5.4 KB
app/src/main/res/drawable-xhdpi/ic_flash_on_sel.png
0 → 100644
5.26 KB
app/src/main/res/drawable-xhdpi/ic_switch_camera.png
0 → 100644
5.35 KB
app/src/main/res/drawable-xhdpi/ic_switch_camera_sel.png
0 → 100644
5.36 KB
app/src/main/res/drawable-xxhdpi/ic_bubble.png
0 → 100644
10.5 KB
app/src/main/res/drawable-xxhdpi/ic_bubble_sel.png
0 → 100644
9.94 KB
app/src/main/res/drawable-xxhdpi/ic_close.png
0 → 100644
10.9 KB
app/src/main/res/drawable-xxhdpi/ic_close_on.png
0 → 100644
10.1 KB
app/src/main/res/drawable-xxhdpi/ic_flash_on.png
0 → 100644
9.61 KB
app/src/main/res/drawable-xxhdpi/ic_flash_on_sel.png
0 → 100644
9.46 KB
app/src/main/res/drawable-xxhdpi/ic_switch_camera.png
0 → 100644
9.68 KB
app/src/main/res/drawable-xxhdpi/ic_switch_camera_sel.png
0 → 100644
9.55 KB
app/src/main/res/drawable-xxhdpi/icon_record_meiyan_off.png
0 → 100644
4.48 KB
app/src/main/res/drawable-xxhdpi/icon_record_meiyan_on.png
0 → 100644
6.14 KB
app/src/main/res/drawable-xxxhdpi/ic_bubble.png
0 → 100644
14.3 KB
app/src/main/res/drawable-xxxhdpi/ic_bubble_sel.png
0 → 100644
13.8 KB
app/src/main/res/drawable-xxxhdpi/ic_close.png
0 → 100644
14.9 KB
app/src/main/res/drawable-xxxhdpi/ic_close_on.png
0 → 100644
14 KB
app/src/main/res/drawable-xxxhdpi/ic_flash_on.png
0 → 100644
13.2 KB
app/src/main/res/drawable-xxxhdpi/ic_flash_on_sel.png
0 → 100644
13.3 KB
app/src/main/res/drawable-xxxhdpi/ic_switch_camera.png
0 → 100644
13 KB
app/src/main/res/drawable-xxxhdpi/ic_switch_camera_sel.png
0 → 100644
13.4 KB
app/src/main/res/drawable/anchor_retry_nor.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<shape xmlns:android="http://schemas.android.com/apk/res/android" | |
| 3 | + android:shape="rectangle"> | |
| 4 | + | |
| 5 | + <corners android:radius="10dp" /> | |
| 6 | + | |
| 7 | + <stroke android:width="1dp" android:color="@android:color/white" android:dashWidth="1px" /> | |
| 8 | +</shape> | |
| 0 | 9 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/btn_record_end.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<shape | |
| 3 | + xmlns:android="http://schemas.android.com/apk/res/android" | |
| 4 | + android:shape="rectangle" | |
| 5 | + android:useLevel="false"> | |
| 6 | + <solid android:color="@android:color/transparent" /> | |
| 7 | + | |
| 8 | + <stroke | |
| 9 | + android:width="3px" | |
| 10 | + android:color="#fbdb44" /> <!-- 定义描边的宽度和描边的颜色值 --> | |
| 11 | + | |
| 12 | + <size | |
| 13 | + android:height="40dp" | |
| 14 | + android:width="275dp"/> | |
| 15 | + | |
| 16 | + <corners | |
| 17 | + android:radius="10dp" /> | |
| 18 | +</shape> | |
| 0 | 19 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/icon_record_close.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
| 3 | + | |
| 4 | + <item android:drawable="@drawable/ic_close_on" android:state_pressed="true" /> | |
| 5 | + <item android:drawable="@drawable/ic_close" android:state_pressed="false" /> | |
| 6 | +</selector> | |
| 0 | 7 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/icon_record_flash.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
| 3 | + <item android:drawable="@drawable/ic_flash_on_sel" android:state_pressed="true" /> | |
| 4 | + <item android:drawable="@drawable/ic_flash_on" android:state_pressed="false" /> | |
| 5 | +</selector> | |
| 0 | 6 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/icon_record_flip.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
| 3 | + | |
| 4 | + <item android:drawable="@drawable/ic_switch_camera_sel" android:state_pressed="true" /> | |
| 5 | + <item android:drawable="@drawable/ic_switch_camera" android:state_pressed="false" /> | |
| 6 | +</selector> | |
| 0 | 7 | \ No newline at end of file | ... | ... |
app/src/main/res/layout/activity_stream_portrait.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<layout xmlns:android="http://schemas.android.com/apk/res/android" | |
| 3 | + xmlns:app="http://schemas.android.com/apk/res-auto" | |
| 4 | + xmlns:tools="http://schemas.android.com/tools"> | |
| 5 | + | |
| 6 | + <data> | |
| 7 | + | |
| 8 | + <variable | |
| 9 | + name="isShow" | |
| 10 | + type="com.cnlive.gundam.stream.model.ShowView" /> | |
| 11 | + | |
| 12 | + <variable | |
| 13 | + name="chatAdapter" | |
| 14 | + type="com.cnlive.gundam.stream.ui.adapter.SimpleAdapter" /> | |
| 15 | + </data> | |
| 16 | + | |
| 17 | + <RelativeLayout | |
| 18 | + android:layout_width="match_parent" | |
| 19 | + android:layout_height="match_parent" | |
| 20 | + tools:context="com.cnlive.granzon.streamer.StreamActivity"> | |
| 21 | + | |
| 22 | + <android.opengl.GLSurfaceView | |
| 23 | + android:id="@+id/camera_preview" | |
| 24 | + android:layout_width="match_parent" | |
| 25 | + android:layout_height="match_parent" | |
| 26 | + android:layout_alignParentBottom="true" | |
| 27 | + android:layout_alignParentTop="true" /> | |
| 28 | + | |
| 29 | + <TextView | |
| 30 | + android:id="@+id/viewers" | |
| 31 | + android:layout_width="wrap_content" | |
| 32 | + android:layout_height="wrap_content" | |
| 33 | + android:layout_marginLeft="10dp" | |
| 34 | + android:layout_marginTop="5dp" | |
| 35 | + android:text="0人" | |
| 36 | + android:textColor="@android:color/white" | |
| 37 | + android:textSize="12sp" | |
| 38 | + android:visibility="@{isShow.viewers ? 0 : 8}" | |
| 39 | + tools:text="62人" /> | |
| 40 | + | |
| 41 | + <RelativeLayout | |
| 42 | + android:layout_width="300dp" | |
| 43 | + android:layout_height="200dp" | |
| 44 | + android:layout_alignParentBottom="true" | |
| 45 | + android:layout_alignParentLeft="true" | |
| 46 | + android:layout_alignParentStart="true"> | |
| 47 | + | |
| 48 | + <android.support.v7.widget.RecyclerView | |
| 49 | + android:id="@+id/chat_recycler_view" | |
| 50 | + android:layout_width="match_parent" | |
| 51 | + android:layout_height="match_parent" | |
| 52 | + android:divider="@null" | |
| 53 | + android:scrollbars="none" | |
| 54 | + android:stackFromBottom="true" | |
| 55 | + android:transcriptMode="alwaysScroll" | |
| 56 | + android:visibility="@{isShow.chatView ? 0 : 8}" | |
| 57 | + app:adapter="@{chatAdapter}" /> | |
| 58 | + </RelativeLayout> | |
| 59 | + | |
| 60 | + <RelativeLayout | |
| 61 | + android:id="@+id/end_layout" | |
| 62 | + android:layout_width="match_parent" | |
| 63 | + android:layout_height="match_parent" | |
| 64 | + android:background="#E6000000" | |
| 65 | + android:gravity="center_horizontal" | |
| 66 | + android:visibility="@{isShow.endLayout ? 0 : 8}"> | |
| 67 | + | |
| 68 | + <RelativeLayout | |
| 69 | + android:id="@+id/main_layout" | |
| 70 | + android:layout_width="match_parent" | |
| 71 | + android:layout_height="wrap_content" | |
| 72 | + android:layout_centerHorizontal="true" | |
| 73 | + android:layout_centerVertical="true"> | |
| 74 | + | |
| 75 | + <TextView | |
| 76 | + android:id="@+id/end_tag" | |
| 77 | + android:layout_width="wrap_content" | |
| 78 | + android:layout_height="wrap_content" | |
| 79 | + android:layout_centerHorizontal="true" | |
| 80 | + android:layout_marginTop="0dp" | |
| 81 | + android:text="直播已结束" | |
| 82 | + android:textColor="#fbdb44" | |
| 83 | + android:textSize="28sp" /> | |
| 84 | + | |
| 85 | + | |
| 86 | + <TextView | |
| 87 | + android:id="@+id/end_view" | |
| 88 | + android:layout_width="wrap_content" | |
| 89 | + android:layout_height="wrap_content" | |
| 90 | + android:layout_below="@+id/end_tag" | |
| 91 | + android:layout_centerHorizontal="true" | |
| 92 | + android:layout_marginTop="40dp" | |
| 93 | + android:gravity="center" | |
| 94 | + android:text="感谢大家观看\n我们下次再见ლ(❛◡❛✿)ლ" | |
| 95 | + android:textColor="@android:color/white" | |
| 96 | + android:textSize="18sp" /> | |
| 97 | + | |
| 98 | + <!--<TextView--> | |
| 99 | + <!--android:id="@+id/end_like"--> | |
| 100 | + <!--android:layout_width="wrap_content"--> | |
| 101 | + <!--android:layout_height="wrap_content"--> | |
| 102 | + <!--android:layout_below="@+id/end_view"--> | |
| 103 | + <!--android:layout_centerHorizontal="true"--> | |
| 104 | + <!--android:layout_marginTop="15dp"--> | |
| 105 | + <!--android:text="0人喜欢"--> | |
| 106 | + <!--android:textColor="@android:color/white"--> | |
| 107 | + <!--android:textSize="18sp" />--> | |
| 108 | + | |
| 109 | + <!--<TextView--> | |
| 110 | + <!--android:id="@+id/end_award"--> | |
| 111 | + <!--android:layout_width="wrap_content"--> | |
| 112 | + <!--android:layout_height="wrap_content"--> | |
| 113 | + <!--android:layout_below="@+id/end_like"--> | |
| 114 | + <!--android:layout_centerHorizontal="true"--> | |
| 115 | + <!--android:layout_marginTop="30dp"--> | |
| 116 | + <!--android:text="本次直播收货 0 中国币"--> | |
| 117 | + <!--android:textColor="@android:color/white"--> | |
| 118 | + <!--android:textSize="18sp" />--> | |
| 119 | + | |
| 120 | + | |
| 121 | + <Button | |
| 122 | + android:id="@+id/btn_end_close" | |
| 123 | + android:layout_width="wrap_content" | |
| 124 | + android:layout_height="42dp" | |
| 125 | + android:layout_below="@+id/end_view" | |
| 126 | + android:layout_centerHorizontal="true" | |
| 127 | + android:layout_marginTop="48dp" | |
| 128 | + android:background="@drawable/btn_record_end" | |
| 129 | + android:onClick="onClick" | |
| 130 | + android:text="知道了" | |
| 131 | + android:textColor="@android:color/white" | |
| 132 | + android:textSize="18sp" /> | |
| 133 | + | |
| 134 | + <TextView | |
| 135 | + android:id="@+id/msg_hint" | |
| 136 | + android:layout_width="wrap_content" | |
| 137 | + android:layout_height="wrap_content" | |
| 138 | + android:layout_below="@id/btn_end_close" | |
| 139 | + android:layout_centerHorizontal="true" | |
| 140 | + android:layout_marginTop="20dp" | |
| 141 | + android:text="抱歉,连接已断开" | |
| 142 | + android:textColor="#ff0000" | |
| 143 | + android:visibility="gone" /> | |
| 144 | + | |
| 145 | + </RelativeLayout> | |
| 146 | + </RelativeLayout> | |
| 147 | + | |
| 148 | + <LinearLayout | |
| 149 | + android:id="@+id/record_btns" | |
| 150 | + android:layout_width="wrap_content" | |
| 151 | + android:layout_height="wrap_content" | |
| 152 | + android:layout_alignParentEnd="true" | |
| 153 | + android:layout_alignParentRight="true" | |
| 154 | + android:orientation="horizontal" | |
| 155 | + android:visibility="@{isShow.recordBtns ? 0 : 8}"> | |
| 156 | + | |
| 157 | + <ImageButton | |
| 158 | + android:id="@+id/btn_beautiful" | |
| 159 | + android:layout_width="43dp" | |
| 160 | + android:layout_height="43dp" | |
| 161 | + android:background="@null" | |
| 162 | + android:onClick="onClick" | |
| 163 | + android:padding="5dp" | |
| 164 | + android:scaleType="fitCenter" | |
| 165 | + android:src="@{isShow.beautifulBtn ? @drawable/icon_record_meiyan_on : @drawable/icon_record_meiyan_off}" /> | |
| 166 | + | |
| 167 | + <ImageButton | |
| 168 | + android:id="@+id/btn_flip" | |
| 169 | + android:layout_width="43dp" | |
| 170 | + android:layout_height="43dp" | |
| 171 | + android:background="@null" | |
| 172 | + android:onClick="onClick" | |
| 173 | + android:padding="5dp" | |
| 174 | + android:scaleType="fitCenter" | |
| 175 | + android:src="@drawable/icon_record_flip" /> | |
| 176 | + | |
| 177 | + <ImageButton | |
| 178 | + android:id="@+id/btn_flash" | |
| 179 | + android:layout_width="43dp" | |
| 180 | + android:layout_height="43dp" | |
| 181 | + android:background="@null" | |
| 182 | + android:onClick="onClick" | |
| 183 | + android:padding="5dp" | |
| 184 | + android:scaleType="fitCenter" | |
| 185 | + android:src="@drawable/icon_record_flash" | |
| 186 | + android:visibility="@{isShow.flashBtn ? 0 : 8}" /> | |
| 187 | + | |
| 188 | + <ImageButton | |
| 189 | + android:id="@+id/btn_close" | |
| 190 | + android:layout_width="43dp" | |
| 191 | + android:layout_height="43dp" | |
| 192 | + android:layout_marginEnd="5dp" | |
| 193 | + android:layout_marginRight="5dp" | |
| 194 | + android:background="@null" | |
| 195 | + android:onClick="onClick" | |
| 196 | + android:padding="5dp" | |
| 197 | + android:scaleType="fitCenter" | |
| 198 | + android:src="@drawable/icon_record_close" /> | |
| 199 | + </LinearLayout> | |
| 200 | + | |
| 201 | + <Button | |
| 202 | + android:id="@+id/startStream" | |
| 203 | + android:layout_width="wrap_content" | |
| 204 | + android:layout_height="wrap_content" | |
| 205 | + android:layout_centerInParent="true" | |
| 206 | + android:background="@drawable/anchor_retry_nor" | |
| 207 | + android:onClick="onClick" | |
| 208 | + android:padding="5dp" | |
| 209 | + android:text="开始直播" | |
| 210 | + android:textColor="@android:color/white" | |
| 211 | + android:visibility="@{isShow.startBtn ? 0 : 8}" /> | |
| 212 | + | |
| 213 | + <RelativeLayout | |
| 214 | + android:id="@+id/retry_layout" | |
| 215 | + android:layout_width="wrap_content" | |
| 216 | + android:layout_height="wrap_content" | |
| 217 | + android:layout_centerInParent="true" | |
| 218 | + android:visibility="@{isShow.retryLayout ? 0 : 8}"> | |
| 219 | + | |
| 220 | + <TextView | |
| 221 | + android:id="@+id/text_retry" | |
| 222 | + android:layout_width="wrap_content" | |
| 223 | + android:layout_height="wrap_content" | |
| 224 | + android:layout_centerHorizontal="true" | |
| 225 | + android:text="直播过程中出现了小问题" | |
| 226 | + android:textColor="@android:color/white" | |
| 227 | + android:textSize="18sp" /> | |
| 228 | + | |
| 229 | + <TextView | |
| 230 | + android:id="@+id/auto_reconnect_msg" | |
| 231 | + android:layout_width="wrap_content" | |
| 232 | + android:layout_height="wrap_content" | |
| 233 | + android:layout_below="@+id/text_retry" | |
| 234 | + android:layout_centerHorizontal="true" | |
| 235 | + android:layout_marginTop="8dp" | |
| 236 | + android:text="@{isShow.autoRectTxt ? @string/reconnecting : @string/reconnect_done}" | |
| 237 | + android:textColor="#fb8640" | |
| 238 | + android:visibility="@{isShow.autoRecMsg ? 0 : 8}" /> | |
| 239 | + | |
| 240 | + <TextView | |
| 241 | + android:id="@+id/button_retry" | |
| 242 | + android:layout_width="wrap_content" | |
| 243 | + android:layout_height="wrap_content" | |
| 244 | + android:layout_below="@+id/auto_reconnect_msg" | |
| 245 | + android:layout_centerHorizontal="true" | |
| 246 | + android:layout_marginTop="8dp" | |
| 247 | + android:background="@drawable/anchor_retry_nor" | |
| 248 | + android:onClick="onClick" | |
| 249 | + android:paddingBottom="8dp" | |
| 250 | + android:paddingLeft="15dp" | |
| 251 | + android:paddingRight="15dp" | |
| 252 | + android:paddingTop="8dp" | |
| 253 | + android:text="点击重试" | |
| 254 | + android:textColor="@android:color/white" | |
| 255 | + android:textSize="18sp" /> | |
| 256 | + | |
| 257 | + </RelativeLayout> | |
| 258 | + | |
| 259 | + </RelativeLayout> | |
| 260 | +</layout> | |
| 0 | 261 | \ No newline at end of file | ... | ... |
app/src/main/res/layout/item_chat.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | |
| 2 | +<layout xmlns:android="http://schemas.android.com/apk/res/android"> | |
| 3 | + | |
| 4 | + <data> | |
| 5 | + <variable | |
| 6 | + name="chat" | |
| 7 | + type="com.cnlive.gundam.stream.model.ChatItem" /> | |
| 8 | + </data> | |
| 9 | + | |
| 10 | + <RelativeLayout | |
| 11 | + android:layout_width="wrap_content" | |
| 12 | + android:layout_height="wrap_content" | |
| 13 | + android:paddingBottom="10dp" | |
| 14 | + android:paddingTop="10dp"> | |
| 15 | + | |
| 16 | + <!--<ImageView--> | |
| 17 | + <!--android:id="@+id/chat_head"--> | |
| 18 | + <!--android:layout_width="43dp"--> | |
| 19 | + <!--android:layout_height="43dp"--> | |
| 20 | + <!--android:layout_centerVertical="true" />--> | |
| 21 | + | |
| 22 | + <TextView | |
| 23 | + android:id="@+id/chat_name" | |
| 24 | + android:layout_width="wrap_content" | |
| 25 | + android:layout_height="wrap_content" | |
| 26 | + android:layout_centerVertical="true" | |
| 27 | + android:layout_marginLeft="5dp" | |
| 28 | + android:text="@{chat.userName + @string/colon}" | |
| 29 | + android:textColor="#ff8800" /> | |
| 30 | + | |
| 31 | + <TextView | |
| 32 | + android:id="@+id/chat_content" | |
| 33 | + android:layout_width="wrap_content" | |
| 34 | + android:layout_height="wrap_content" | |
| 35 | + android:layout_centerVertical="true" | |
| 36 | + android:layout_marginLeft="5dp" | |
| 37 | + android:layout_toRightOf="@+id/chat_name" | |
| 38 | + android:text="@{chat.content}" | |
| 39 | + android:textColor="@android:color/white" /> | |
| 40 | + | |
| 41 | + </RelativeLayout> | |
| 42 | + | |
| 43 | +</layout> | |
| 0 | 44 | \ No newline at end of file | ... | ... |
app/src/main/res/values/strings.xml
| ... | ... | @@ -5,4 +5,11 @@ |
| 5 | 5 | <string name="main_tab_live_tv">电视台</string> |
| 6 | 6 | <string name="main_tab_live">直播</string> |
| 7 | 7 | <string name="main_tab_mine">我的</string> |
| 8 | + | |
| 9 | + <string name="reconnecting">正在尝试自动重连。。。</string> | |
| 10 | + <string name="reconnect_done">Oops 自动重连失败</string> | |
| 11 | + <string name="colon"> : </string> | |
| 12 | + | |
| 13 | + <!-- TODO: Remove or change this placeholder text --> | |
| 14 | + <string name="hello_blank_fragment">Hello blank fragment</string> | |
| 8 | 15 | </resources> | ... | ... |