騰訊雲直播初體驗
阿新 • • 發佈:2019-01-04
移動直播安卓的整合其實相對簡單,主要分為推流端功能和播放端功能,主要實現條件大致分為以下三點:
①RTMP SDK整合與使用
②拼接出推流地址(可由後臺伺服器提供)
③拼接出播放地址(可由後臺伺服器提供)
***本文將主要介紹SDK的整合和功能實現方案。***
一、RTMP SDK整合
① [SDK下載地址](https://www.qcloud.com/product/mlvb#wiki)
解壓後可看到以下檔案
將jar包複製到專案下的libs檔案。在專案的main資料夾下新建jniLibs資料夾將so檔案拷貝進去,同步下專案生成如下專案結構。
②配置相關的許可權
[java] view plain- <uses-permission android:name=“android.permission.INTERNET” />
- <uses-permission android: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-permission android: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” />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android: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-permission android: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" />
注意:安卓6.0以後的系統需要在程式碼中動態獲取相機、麥克風、sd卡許可權,相關方法百度很多就不在過多贅述,謹在此提供一下小編的一種方案
[java] view plain copy print?- privatestaticfinalint REQUEST_EXTERNAL_STORAGE = 1;
- privatestatic String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
- privateboolean checkedPermission;
- privatevoid checkPermission() {
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
- != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
- != PackageManager.PERMISSION_GRANTED) {
- //進入到這裡代表沒有許可權.
- if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) {
- //已經禁止提示了
- Toast.makeText(MainActivity.this, TCConstants.ERROR_MSG_PERMISSION_FORBID, Toast.LENGTH_SHORT).show();
- } else {
- ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
- }
- } else {
- checkedPermission = true;
- }
- }
- @Override
- publicvoid onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNullint[] grantResults) {
- switch (requestCode) {
- case REQUEST_EXTERNAL_STORAGE:
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- //使用者同意授權
- checkedPermission = true;
- }
- break;
- }
- }
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
private boolean checkedPermission;
private void checkPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
//進入到這裡代表沒有許可權.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) {
//已經禁止提示了
Toast.makeText(MainActivity.this, TCConstants.ERROR_MSG_PERMISSION_FORBID, Toast.LENGTH_SHORT).show();
} else {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} else {
checkedPermission = true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//使用者同意授權
checkedPermission = true;
}
break;
}
}
③驗證SDK配置情況 [java] view plain copy print?
- //在onCreate中呼叫getSDKVersion介面獲取版本號:
- int[] sdkver = TXLivePusher.getSDKVersion();
- if (sdkver != null && sdkver.length >= 3) {
- Log.d(”rtmpsdk”,“rtmp sdk version is:” + sdkver[0] + “.” + sdkver[1] + “.” + sdkver[2]);
- }
//在onCreate中呼叫getSDKVersion介面獲取版本號:
int[] sdkver = TXLivePusher.getSDKVersion();
if (sdkver != null && sdkver.length >= 3) {
Log.d("rtmpsdk","rtmp sdk version is:" + sdkver[0] + "." + sdkver[1] + "." + sdkver[2]);
}
執行之後將在logcat中看到如下log資訊:07-1320:25:05.09926119-26119/? D/rtmpsdk: rtmp sdk version is:1.5.188
二、主播端推流功能實現
①視訊播放器,用於給主播展示推流的視訊
[java] view plain copy print?- <span style=“font-size:18px;”><com.tencent.rtmp.ui.TXCloudVideoView
- android:id=”@+id/video_view”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent” /></span>
<com.tencent.rtmp.ui.TXCloudVideoView
android:id="@+id/video_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
②開啟推流
[java] view plain copy print?- //推流相關
- private TXCloudVideoView mTXCloudVideoView;
- private TXLivePusher mTXLivePusher;
- private TXLivePushConfig mTXPushConfig = new TXLivePushConfig();
- //開啟推流
- protectedvoid startPublish() {
- if (mTXLivePusher == null) {
- mTXLivePusher = new TXLivePusher(this);
- mTXLivePusher.setConfig(mTXPushConfig);
- }
- //可由伺服器拼接此推流地址
- mTXLivePusher.startPusher(TCConstants.PUBLISH_URL);
- mTXLivePusher.startCameraPreview(mTXCloudVideoView);
- }
//推流相關
private TXCloudVideoView mTXCloudVideoView;
private TXLivePusher mTXLivePusher;
private TXLivePushConfig mTXPushConfig = new TXLivePushConfig();
//開啟推流
protected void startPublish() {
if (mTXLivePusher == null) {
mTXLivePusher = new TXLivePusher(this);
mTXLivePusher.setConfig(mTXPushConfig);
}
//可由伺服器拼接此推流地址
mTXLivePusher.startPusher(TCConstants.PUBLISH_URL);
mTXLivePusher.startCameraPreview(mTXCloudVideoView);
}
③停止推流,注意結束推流很簡單,不過要做好清理工作,因為用於推流的 TXLivePusher 和用於顯示影像的 TXCloudVideoView 都是不能多例項並行運轉的,所以清理工作不當會導致下次直播遭受不良的影響。[java] view plain copy print?
- //停止推流
- protectedvoid stopPublish() {
- if (mTXLivePusher != null) {
- mTXLivePusher.stopCameraPreview(true);//停止攝像頭預覽
- mTXLivePusher.stopPusher();//停止推流
- mTXLivePusher.setPushListener(null);//解綁 listener
- }
- this.finish();
- }
//停止推流
protected void stopPublish() {
if (mTXLivePusher != null) {
mTXLivePusher.stopCameraPreview(true);//停止攝像頭預覽
mTXLivePusher.stopPusher();//停止推流
mTXLivePusher.setPushListener(null);//解綁 listener
}
this.finish();
}
三、客戶端視訊播放
①準備視訊播放器
- <com.tencent.rtmp.ui.TXCloudVideoView
- android:id=”@+id/play_view”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent” />
<com.tencent.rtmp.ui.TXCloudVideoView
android:id="@+id/play_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
②開始播放
[java] view plain copy print?- private TXCloudVideoView playerView;
- private TXLivePlayer livePlayer;
- protectedvoid starPlay() {
- //建立player物件
- livePlayer = new TXLivePlayer(this);
- //關聯player物件與介面view
- livePlayer.setPlayerView(playerView);
- livePlayer.setConfig(new TXLivePlayConfig());
- livePlayer.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);
- //推薦FLV播放格式
- livePlayer.startPlay(TCConstants.PLAY_URL, TXLivePlayer.PLAY_TYPE_LIVE_FLV);
- }
private TXCloudVideoView playerView;
private TXLivePlayer livePlayer;
protected void starPlay() {
//建立player物件
livePlayer = new TXLivePlayer(this);
//關聯player物件與介面view
livePlayer.setPlayerView(playerView);
livePlayer.setConfig(new TXLivePlayConfig());
livePlayer.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);
//推薦FLV播放格式
livePlayer.startPlay(TCConstants.PLAY_URL, TXLivePlayer.PLAY_TYPE_LIVE_FLV);
}
③停止播放
[java] view plain copy print?- protectedvoid stopPlay() {
- if (playerView != null) {
- livePlayer.setPlayListener(null);
- livePlayer.stopPlay(true);
- playerView.onDestroy();
- }
- this.finish();
- }
protected void stopPlay() {
if (playerView != null) {
livePlayer.setPlayListener(null);
livePlayer.stopPlay(true);
playerView.onDestroy();
}
this.finish();
}
到此直播的基本功能已經實現了,後續會介紹一些精細的用法和注意的地方,敬請期待。有什麼問題可以在評論區留言,相互交流,我會不定期回覆解答