腾讯云直播初体验

xiaoxiao2021-02-27  263

转自:http://blog.csdn.net/g_ying_jie/article/details/72818519

移动直播安卓的集成其实相对简单,主要分为推流端功能和播放端功能,主要实现条件大致分为以下三点: ①RTMP SDK集成与使用 ②拼接出推流地址(可由后台服务器提供) ③拼接出播放地址(可由后台服务器提供) ***本文将主要介绍SDK的集成和功能实现方案。*** 一、RTMP SDK集成

① [SDK下载地址](https://www.qcloud.com/product/mlvb#wiki)

解压后可看到以下文件

将jar包复制到项目下的libs文件。在项目的main文件夹下新建jniLibs文件夹将so文件拷贝进去,同步下项目生成如下项目结构。

②配置相关的权限

[java] view plain copy print ? <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 ? 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;      }  }   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-13 20:25:05.099 26119-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();    //开启推流  protected void 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 ? //停止推流  protected void 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(); }

三、客户端视频播放

①准备视频播放器

[java] view plain copy print ? <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;  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);  }   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 ? protected void 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(); }

到此直播的基本功能已经实现了,后续会介绍一些精细的用法和注意的地方,敬请期待。有什么问题可以在评论区留言,相互交流,我会不定期回复解答

转载请注明原文地址: https://www.6miu.com/read-10397.html

最新回复(0)