版权声明:本文为博主原创文章,转载注明出处,欢迎多多交流,乐在沟通,有需要请联系邮箱:[email protected] https://blog.csdn.net/weixin_42749765/article/details/88074995
目录
前言:
最近公司打算做先关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 地址:
- https://download.csdn.net/download/weixin_42749765/10989862
- 功能包括:开启直播,推流,关闭直播,切换摄像头
- 一些其他的功能可以通过文档中自行加入
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(防盗链签名)
- 文档:https://cloud.tencent.com/document/product/454/9875
- 去控制台获取推流防盗链key 就是下边代码 7d5xxxxxxxxxxxxxxxxxf03c8e
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
持续更新!