java后台程序员转android 《三》之 集成腾讯云 云直播 直播推流端,接受展示端,后台server端 及采坑记录

版权声明:本文为博主原创文章,转载注明出处,欢迎多多交流,乐在沟通,有需要请联系邮箱:[email protected] https://blog.csdn.net/weixin_42749765/article/details/88074995

目录

前言:

1.腾讯云直播文档:

2.demo 地址:

3.android 主播端实例代码如下:

3.1.activity.xml

3.2.java代码

4.查看主播端图片效果:

5.通过webview 的方式  实现html客户端查看直播

5.1html 代码

6.查看 直播客户端图片效果

7.集成server 后台服务派发URL(防盗链签名)

7.1用来生成直播验证代码签名

7.2介绍:

8.总结


前言:


最近公司打算做先关android 方面的技术,然后招andirod 还挺贵,老板打算让我来搞搞,那就搞一搞,顺便做些总结,从java后台转型快速入手 android 的小策略。

andoird 官网地址 https://developer.android.google.cn/

1.腾讯云直播文档:

直播文档接入:https://cloud.tencent.com/document/product/267/30559

android 集成 :https://cloud.tencent.com/document/product/454/14407

android 集成接入 :https://cloud.tencent.com/document/product/454/7877

2.demo 地址:

3.android 主播端实例代码如下:

3.1.activity.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#DC4D41"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/s1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginBottom="10dp"
        android:onClick="clickLiveStart"
        android:text="开启"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/s4"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginStart="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginBottom="10dp"
        android:onClick="clickLiveShutdown"
        android:text="关闭"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/s5" />

    <Button
        android:id="@+id/s5"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_marginStart="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginBottom="10dp"
        android:onClick="clickliveqhCamera"
        android:text="切换摄像头"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/s1" />




    <com.tencent.rtmp.ui.TXCloudVideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:visibility="gone" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:text="退出"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"
        android:text="貂蝉宝石直播间"
        android:textColor="#fff"
        android:textSize="18sp"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="196dp" />


</android.support.constraint.ConstraintLayout>

3.2.java代码

package com.example.appvediotxy;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import com.tencent.imsdk.TIMCallBack;
import com.tencent.imsdk.TIMConversation;
import com.tencent.imsdk.TIMConversationType;
import com.tencent.imsdk.TIMLogLevel;
import com.tencent.imsdk.TIMManager;
import com.tencent.imsdk.TIMMessage;
import com.tencent.imsdk.TIMSdkConfig;
import com.tencent.imsdk.TIMTextElem;
import com.tencent.imsdk.TIMValueCallBack;
import com.tencent.rtmp.TXLivePlayer;
import com.tencent.rtmp.TXLivePushConfig;
import com.tencent.rtmp.TXLivePusher;
import com.tencent.rtmp.ui.TXCloudVideoView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    //推流
    private TXLivePusher mLivePusher;
    private TXLivePushConfig mLivePushConfig;
    //推流地址音频 推流域名从腾讯云服务器上获取
    private String rtmpUrl = "rtmp://推流域名/live/222?txSecret=36d31b175e76b7e3b87e2e5e4e225f71&txTime=5C75627F";

    private TXLivePlayer mLivePlayer;
    private TXCloudVideoView  mView;
    //推流地址视频
    private String flvUrl = "http://推流域名/live/222.flv";

    //初始化直播
    public void initInfo(){
        //从服务端获取直播信息
        statuplive();
    }

    //开启直播推流
    public void clickLiveStart(View v) {
        statuplive();
    }

    //开启直播
    public void statuplive(){
        //推流
        mLivePusher = new TXLivePusher(MainActivity.this);//获取开启
        mLivePushConfig = new TXLivePushConfig();//配置内容
        mLivePusher.setConfig(mLivePushConfig); //加载配置
        mLivePusher.startPusher(rtmpUrl);//开启推流

        //视频顺便展示在当前界面上
        TXCloudVideoView mCaptureView = (TXCloudVideoView) findViewById(R.id.video_view);
        mLivePusher.startCameraPreview(mCaptureView);
        mView = (TXCloudVideoView) findViewById(R.id.video_view);
        mLivePlayer = new TXLivePlayer(MainActivity.this);//创建 player 对象
        mLivePlayer.setPlayerView(mView);//关键 player 对象与界面 view
        mLivePlayer.startPlay(flvUrl, TXLivePlayer.PLAY_TYPE_LIVE_FLV); //推荐 FLV
    }

    //关闭直播结束推流
    public void clickLiveShutdown(View v){
        mLivePusher.stopCameraPreview(true); //停止摄像头预览
        mLivePusher.stopPusher();            //停止推流
        mLivePusher.setPushListener(null);   //解绑 listener

    }

    //切换前后摄像头
    public void clickliveqhCamera(View v){
        // 默认是前置摄像头
        mLivePusher.switchCamera();
    }

    //关闭直播
    @Override
    public void onDestroy() {
        super.onDestroy();
        mLivePlayer.stopPlay(true); // true 代表清除最后一帧画面
        mView.onDestroy();
    }


}

4.查看主播端图片效果:

5.通过webview 的方式  实现html客户端查看直播

5.1html 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>liveClient</title>
    
    <!-- 加载全局类库 -->
    <script type="text/javascript" src="../libs/jquery.js"></script>
    <script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.2.1.js" charset="utf-8"></script>;


</head>
<body>
     <!-- 首页div -->
    <div class="globalA">
        <div id="id_test_video" style="width:100%; height:auto;"></div>
        <div class="demoA"></div>
    </div>
</body>
<script>
$(document).ready(function(){
     //查看直播模块
        var nowimgUrl = "http://pic40.photophoto.cn/20160710/1155115962721749_b.jpg";
        var player = new TcPlayer('id_test_video', {
            "m3u8": "http://abc.xxx.com/live/222.m3u8", //请替换成实际可用的播放地址
            "autoplay" : true,      //iOS下safari浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的
            "coverpic" : {"style":"cover","src":nowimgUrl},
            "width" :  '480',//视频的显示宽度,请尽量使用视频分辨率宽度
            "height" : '320',//视频的显示高度,请尽量使用视频分辨率高度
           
            });
});
</script>
</html>

6.查看 直播客户端图片效果

 

7.集成server 后台服务派发URL(防盗链签名)

7.1用来生成直播验证代码签名

package com.supermap.test;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * 生成 直播验证内容
 * @author yushen
 *
 */
public class TestTxyLive {

	public static void main(String[] args) {
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Long maxTime = dateToTimestamp(sdf.format(getEndOfDay(date)).toString());
		String newurl = getSafeUrl("7d5xxxxxxxxxxxxxxxxxf03c8e", "222", maxTime);

		System.out.println(newurl);
	}
	
	//时间转时间戳
	public static long dateToTimestamp(String time) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date date = simpleDateFormat.parse(time);
			long ts = date.getTime() / 1000;
			return ts;
		} catch (ParseException e) {
			return 0;
		}
	}

	// 获得某天最大时间 2017-10-15 23:59:59
	public static Date getEndOfDay(Date date) {
		LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()),
				ZoneId.systemDefault());
		LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
		return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
	}

	private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
			'e', 'f' };

	/*
	 * KEY+ streamName + txTime
	 */
	private static String getSafeUrl(String key, String streamName, long txTime) {
		String input = new StringBuilder().append(key).append(streamName).append(Long.toHexString(txTime).toUpperCase())
				.toString();

		String txSecret = null;
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			txSecret = byteArrayToHexString(messageDigest.digest(input.getBytes("UTF-8")));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return txSecret == null ? ""
				: new StringBuilder().append("txSecret=").append(txSecret).append("&").append("txTime=")
						.append(Long.toHexString(txTime).toUpperCase()).toString();
	}

	private static String byteArrayToHexString(byte[] data) {
		char[] out = new char[data.length << 1];

		for (int i = 0, j = 0; i < data.length; i++) {
			out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
			out[j++] = DIGITS_LOWER[0x0F & data[i]];
		}
		return new String(out);
	}
}

7.2介绍:


  • 执行完后
  • 会生成这么个东东
  • txSecret=c072522e6b96e521cdcfebce5cbb1b86&txTime=5C7AA87F
  • 用来验证安全的
  • 将这个签名放到推流地址的后边就ok楼

8.总结

  • 1.第一步查看官方文档
  • 2.实现主播端android 开发
  • 3.实现客户端html的查看视频
  • 4.实现服务端的配置推流安全防盗链
  • ok

持续更新!

猜你喜欢

转载自blog.csdn.net/weixin_42749765/article/details/88074995