關於Android直播那些小事-推流1
阿新 • • 發佈:2019-02-17
到年底了,閒暇之餘學了點熱門的東西,直播現在是很火的,所以我也玩玩直播,弄了個demo,準備玩一玩,這是第一篇,先說一下推流實現直播功能,陸續會有很多互動demo的功能,今天只是簡單的實現一下推流可以從攝像頭採集圖片到View上,這裡推流用的是Rtmp騰訊雲的工具。
1、今天只實現第一個功能直播推流效果是這樣的,按鈕下的功能會陸續實現
2、開發前的準備工作如圖
具體要用到的資源可以去騰訊雲下載的哦。。。。
3、開始裝逼
首先要在清單檔案中新增所需要的許可權:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.Camera"/> <uses-feature android:name="android.hardware.camera.autofocus" />
然後什麼佈局之類的就是輕車熟路了就不在這裡說了,
直接看關於fragment的佈局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.tencent.rtmp.ui.TXCloudVideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:visibility="gone"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="10dp" android:layout_gravity="bottom"> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnPlay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/play_start"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnCameraChange" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/camera_change"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnTouchFoucs" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/automatic"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnHWEncode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/quick"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnFaceBeauty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/face_beauty"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnLog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/log_show"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnBitrate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/fix_bitrate"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> <Buttonandroid:id="@+id/btnFlash" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/flash_on"/> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/layoutBitrate" android:layout_marginBottom="0dp" android:background="#FFFFFF" android:visibility="gone" android:clickable="true" android:layout_gravity="bottom"> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="位元速率自適應" android:textSize="16sp" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:layout_weight="1"/> <RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginBottom="25dp" android:visibility="visible" android:id="@+id/resolutionRadioGroup" android:layout_gravity="center_horizontal" android:orientation="horizontal"> <RadioButton style="@style/RadiobuttonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="720P" android:tag="4" android:id="@+id/radio_btn_fix_720p" android:textColor="@color/resolution_radio_color" android:background="@drawable/resolution_radio" /> <RadioButton style="@style/RadiobuttonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="540P" android:tag="3" android:id="@+id/radio_btn_fix_540p" android:textColor="@color/resolution_radio_color" android:background="@drawable/resolution_radio" /> <RadioButton style="@style/RadiobuttonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="360P" android:tag="2" android:id="@+id/radio_btn_fix_360p" android:textColor="@color/resolution_radio_color" android:background="@drawable/resolution_radio" /> <RadioButton style="@style/RadiobuttonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="360+" android:tag="1" android:id="@+id/radio_btn_auto" android:textColor="@color/resolution_radio_color" android:background="@drawable/resolution_radio" /> </RadioGroup> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="15dp" android:minHeight="105dp" android:orientation="vertical" android:id="@+id/layoutFaceBeauty" android:layout_marginBottom="0dp" android:background="#FFFFFF" android:visibility="gone" android:clickable="true" android:layout_gravity="bottom"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:layout_marginBottom="10dp" android:orientation="horizontal"> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="美顏效果" android:textSize="16sp" /> <SeekBar android:id="@+id/beauty_seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="15dp" android:paddingRight="18dp" android:maxHeight="4.0dip" android:minHeight="4.0dip" android:visibility="visible" android:progressDrawable="@drawable/seekbar_progress_drawable" android:thumb="@drawable/circle" android:max="9" android:indeterminate="false" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="美白效果" android:textSize="16sp" /> <SeekBar android:id="@+id/whitening_seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="15dp" android:paddingRight="18dp" android:maxHeight="4.0dip" android:minHeight="4.0dip" android:visibility="visible" android:progressDrawable="@drawable/seekbar_progress_drawable" android:thumb="@drawable/circle" android:max="3" android:indeterminate="false" /> </LinearLayout> </LinearLayout> </FrameLayout>然後就應該看我們的LivePushFragment
/** * 初始化 * @param view */ private void init(View view) { initData(); initView(view); initListener(); }
/** * 初始化推流配置 */ private void initData() { //1初始化推流配置 mLivePusher = new TXLivePusher(getActivity()); mTxLivePushConfig = new TXLivePushConfig(); } /** * 初始化控制元件 * @param view */ private void initView(View view) { //初始化播放view mCaptureView = (TXCloudVideoView) view.findViewById(R.id.video_view); //初始化播放按鈕 mBtnPlay = (Button) view.findViewById(R.id.btnPlay); //初始化攝像頭 mBtnChangeCam = (Button) view.findViewById(R.id.btnCameraChange); }
/** * 初始化監聽方法 */ private void initListener() { //點選開始直播的按鈕 mBtnPlay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mVideoPublish){ stopPulishRtmp(); mVideoPublish = false; }else{ fixOrAdjustBitrate(); mVideoPublish=startPublishRtmp(); } } }); }
//是否開始推流 private boolean mVideoPublish;
/** * 停止推流 */ private void stopPulishRtmp() { //關閉攝像頭 mLivePusher.stopCameraPreview(true); //取消監聽 mLivePusher.setPushListener(null); //停止推送 mLivePusher.stopPusher(); mCaptureView.setVisibility(View.GONE); mBtnPlay.setBackgroundResource(R.drawable.play_start); }
/** * 設定位元速率:預設為自適應位元速率 */ private void fixOrAdjustBitrate() { if(mLivePusher!=null){ //設定顯示畫面 mTxLivePushConfig.setVideoResolution(TXLiveConstants.VIDEO_RESOLUTION_TYPE_360_640); //設定自適應位元速率 mTxLivePushConfig.setAutoAdjustBitrate(true); //設定最大位元速率 mTxLivePushConfig.setMaxVideoBitrate(1000); //設定最小位元速率 mTxLivePushConfig.setMinVideoBitrate(500); //設定常規位元速率 mTxLivePushConfig.setVideoBitrate(700); mLivePusher.setConfig(mTxLivePushConfig); } }
/** * 開始推流 * @return */ private boolean startPublishRtmp() { //獲取推流地址:該地址為測試地址 String rtmpUrl = "rtmp://2000.livepush.myqcloud.com/live/2000_4eb4da7079af11e69776e435c87f075e?bizid=2000"; if (TextUtils.isEmpty(rtmpUrl) || (!rtmpUrl.trim().toLowerCase().startsWith("rtmp://"))) { mVideoPublish = false; Toast.makeText(getActivity().getApplicationContext(), "推流地址不合法,目前支援rtmp推流!", Toast.LENGTH_SHORT).show(); return false; } //設定顯示videoView mCaptureView.setVisibility(View.VISIBLE); //帶測試,可去掉 int customModeType = 0; mTxLivePushConfig.setCustomModeType(customModeType); mLivePusher.setConfig(mTxLivePushConfig); //設定推流監聽 mLivePusher.setPushListener(this); //開啟攝像頭將獲取到的畫面放在videoView上 mLivePusher.startCameraPreview(mCaptureView); //開始推流 mLivePusher.startPusher(rtmpUrl); mBtnPlay.setBackgroundResource(R.drawable.play_pause); return true; } 最後看
PushListener
@Override public void onPushEvent(int event, Bundle bundle) { //斷網的情況下的判斷 if(event==TXLiveConstants.PUSH_ERR_NET_DISCONNECT){ stopPulishRtmp(); mVideoPublish=false; } } @Override public void onNetStatus(Bundle bundle) { } 目前就是簡單的集成了推流功能,剩下的功能陸續上傳,敬請期待。