mirror of
https://github.com/czp3009/bilibili-api.git
synced 2025-02-19 20:50:28 +08:00
在 LiveClient 中加入异步连接的方法
This commit is contained in:
parent
a721bf1d99
commit
77764db610
@ -1,5 +1,5 @@
|
||||
group = 'com.hiczp'
|
||||
version = '0.0.10'
|
||||
version = '0.0.11'
|
||||
description = 'Bilibili android client API library written in Java'
|
||||
|
||||
apply plugin: 'idea'
|
||||
|
@ -393,11 +393,19 @@ public class BilibiliAPI implements BilibiliServiceProvider, BilibiliCaptchaProv
|
||||
return infoEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2018-05-11 现在用假的房间 Id 也能正常连接弹幕推送服务器
|
||||
*
|
||||
* @param eventLoopGroup
|
||||
* @param roomId
|
||||
* @param isRealRoomId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public LiveClient getLiveClient(EventLoopGroup eventLoopGroup, long showRoomId) {
|
||||
public LiveClient getLiveClient(EventLoopGroup eventLoopGroup, long roomId, boolean isRealRoomId) {
|
||||
return bilibiliAccount.getUserId() == null ?
|
||||
new LiveClient(this, eventLoopGroup, showRoomId) :
|
||||
new LiveClient(this, eventLoopGroup, showRoomId, bilibiliAccount.getUserId());
|
||||
new LiveClient(this, eventLoopGroup, roomId, isRealRoomId) :
|
||||
new LiveClient(this, eventLoopGroup, roomId, isRealRoomId, bilibiliAccount.getUserId());
|
||||
}
|
||||
|
||||
private void markCurrentTokenAndRefreshTokenInvalid() {
|
||||
|
@ -99,6 +99,11 @@ public class ServerErrorCode {
|
||||
* "请先登录"
|
||||
*/
|
||||
public static final int NO_LOGIN = -101;
|
||||
/**
|
||||
* 访问的房间号不存在
|
||||
* "message": "Document is not exists."
|
||||
*/
|
||||
public static final int DOCUMENT_IS_NOT_EXISTS = -404;
|
||||
/**
|
||||
* 搜索时, 关键字字数过少或过多
|
||||
* "关键字不能小于2个字节或大于50字节"
|
||||
|
@ -38,6 +38,8 @@ public interface LiveService {
|
||||
* 获取直播间信息
|
||||
* 登录后访问该 API 将在服务器新增一条直播间观看历史
|
||||
*
|
||||
* 2018-05-11 现在用假的房间 ID 也能获得正确的信息
|
||||
*
|
||||
* @param roomId 房间号
|
||||
*/
|
||||
@GET("AppRoom/index")
|
||||
|
@ -24,35 +24,51 @@ import retrofit2.Call;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class LiveClient {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LiveClient.class);
|
||||
|
||||
private static final String DEFAULT_SERVER_ADDRESS = "livecmt-2.bilibili.com";
|
||||
private static final int DEFAULT_SERVER_PORT = 2243;
|
||||
|
||||
private final BilibiliServiceProvider bilibiliServiceProvider;
|
||||
private final EventLoopGroup eventLoopGroup;
|
||||
private final long showRoomId;
|
||||
private final long userId;
|
||||
private final EventBus eventBus = new EventBus("BilibiliLiveClientEventBus");
|
||||
private Long showRoomId;
|
||||
private Long realRoomId;
|
||||
|
||||
private LiveRoomInfoEntity.LiveRoom liveRoom;
|
||||
|
||||
private Channel channel;
|
||||
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, EventLoopGroup eventLoopGroup, long showRoomId, long userId) {
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, @Nonnull EventLoopGroup eventLoopGroup, long roomId, boolean isRealRoomId, long userId) {
|
||||
this.bilibiliServiceProvider = bilibiliServiceProvider;
|
||||
this.eventLoopGroup = eventLoopGroup;
|
||||
this.showRoomId = showRoomId;
|
||||
if (isRealRoomId) {
|
||||
realRoomId = roomId;
|
||||
} else {
|
||||
showRoomId = roomId;
|
||||
}
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, EventLoopGroup eventLoopGroup, long showRoomId) {
|
||||
this(bilibiliServiceProvider, eventLoopGroup, showRoomId, 0);
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, @Nonnull EventLoopGroup eventLoopGroup, long showRoomId, long userId) {
|
||||
this(bilibiliServiceProvider, eventLoopGroup, showRoomId, false, userId);
|
||||
}
|
||||
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, @Nonnull EventLoopGroup eventLoopGroup, long roomId, boolean isRealRoomId) {
|
||||
this(bilibiliServiceProvider, eventLoopGroup, roomId, isRealRoomId, 0);
|
||||
}
|
||||
|
||||
public LiveClient(@Nonnull BilibiliServiceProvider bilibiliServiceProvider, @Nonnull EventLoopGroup eventLoopGroup, long showRoomId) {
|
||||
this(bilibiliServiceProvider, eventLoopGroup, showRoomId, false, 0);
|
||||
}
|
||||
|
||||
public Call<LiveRoomInfoEntity> fetchRoomInfoAsync() {
|
||||
return bilibiliServiceProvider.getLiveService()
|
||||
.getRoomInfo(showRoomId);
|
||||
.getRoomInfo(getShowRoomIdOrRoomId());
|
||||
}
|
||||
|
||||
public LiveRoomInfoEntity.LiveRoom fetchRoomInfo() throws IOException {
|
||||
@ -61,60 +77,75 @@ public class LiveClient {
|
||||
.execute()
|
||||
.body()
|
||||
.getData();
|
||||
//此时 code 为 -404
|
||||
if (liveRoom != null) {
|
||||
return liveRoom;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Target room " + showRoomId + " not exists");
|
||||
throw new IllegalArgumentException("Target room " + getShowRoomIdOrRoomId() + " not exists");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized LiveClient connect() throws IOException {
|
||||
if (channel != null && channel.isActive()) {
|
||||
LOGGER.warn("Already connected to server, connect method can not be invoked twice");
|
||||
public Callable<LiveClient> connectAsync() {
|
||||
return () -> {
|
||||
if (channel != null && channel.isActive()) {
|
||||
LOGGER.warn("Already connected to server, connect method can not be invoked twice");
|
||||
return this;
|
||||
}
|
||||
if (realRoomId == null) {
|
||||
if (liveRoom == null) {
|
||||
LOGGER.info("Fetching info of live room {}", showRoomId);
|
||||
liveRoom = fetchRoomInfo();
|
||||
LOGGER.info("Get actual room id {}", liveRoom.getRoomId());
|
||||
}
|
||||
realRoomId = liveRoom.getRoomId();
|
||||
}
|
||||
|
||||
LOGGER.debug("Init SocketChannel Bootstrap");
|
||||
Bootstrap bootstrap = new Bootstrap()
|
||||
.group(eventLoopGroup)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
socketChannel.pipeline()
|
||||
.addLast(new LengthFieldBasedFrameDecoder(
|
||||
Integer.MAX_VALUE,
|
||||
0,
|
||||
Package.LENGTH_FIELD_LENGTH,
|
||||
-Package.LENGTH_FIELD_LENGTH,
|
||||
0
|
||||
))
|
||||
.addLast(new IdleStateHandler(40, 0, 0))
|
||||
.addLast(new PackageEncoder())
|
||||
.addLast(new PackageDecoder())
|
||||
.addLast(new LiveClientHandler(self(), realRoomId, userId));
|
||||
}
|
||||
});
|
||||
|
||||
String address = liveRoom != null ? liveRoom.getCmt() : DEFAULT_SERVER_ADDRESS;
|
||||
int port = liveRoom != null ? liveRoom.getCmtPortGoim() : DEFAULT_SERVER_PORT;
|
||||
LOGGER.info("Connecting to Bullet Screen server {}:{}", address, port);
|
||||
try {
|
||||
channel = bootstrap.connect(address, port)
|
||||
.sync()
|
||||
.channel();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) { //有可能在此时出现网络错误
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
LOGGER.info("Fetching info of live room {}", showRoomId);
|
||||
liveRoom = fetchRoomInfo();
|
||||
long roomId = liveRoom.getRoomId();
|
||||
LOGGER.info("Get actual room id {}", roomId);
|
||||
public LiveClient connect(ExecutorService executorService) throws InterruptedException, ExecutionException {
|
||||
Future<LiveClient> future = executorService.submit(connectAsync());
|
||||
return future.get();
|
||||
}
|
||||
|
||||
LOGGER.debug("Init SocketChannel Bootstrap");
|
||||
Bootstrap bootstrap = new Bootstrap()
|
||||
.group(eventLoopGroup)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
socketChannel.pipeline()
|
||||
.addLast(new LengthFieldBasedFrameDecoder(
|
||||
Integer.MAX_VALUE,
|
||||
0,
|
||||
Package.LENGTH_FIELD_LENGTH,
|
||||
-Package.LENGTH_FIELD_LENGTH,
|
||||
0
|
||||
))
|
||||
.addLast(new IdleStateHandler(40, 0, 0))
|
||||
.addLast(new PackageEncoder())
|
||||
.addLast(new PackageDecoder())
|
||||
.addLast(new LiveClientHandler(self(), roomId, userId));
|
||||
}
|
||||
});
|
||||
|
||||
String address = liveRoom.getCmt();
|
||||
int port = liveRoom.getCmtPortGoim();
|
||||
LOGGER.info("Connecting to Bullet Screen server {}:{}", address, port);
|
||||
try {
|
||||
channel = bootstrap.connect(address, port)
|
||||
.sync()
|
||||
.channel();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) { //有可能在此时出现网络错误
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
return this;
|
||||
public LiveClient connect() throws InterruptedException, ExecutionException {
|
||||
return connect(Executors.newSingleThreadExecutor());
|
||||
}
|
||||
|
||||
public synchronized ChannelFuture closeChannelAsync() {
|
||||
@ -149,6 +180,8 @@ public class LiveClient {
|
||||
return this;
|
||||
}
|
||||
|
||||
//TODO 弹幕发送队列
|
||||
|
||||
public Call<SendBulletScreenResponseEntity> sendBulletScreenAsync(@Nonnull String message) {
|
||||
return bilibiliServiceProvider.getLiveService()
|
||||
.sendBulletScreen(createBulletScreenEntity(message));
|
||||
@ -160,12 +193,6 @@ public class LiveClient {
|
||||
.body();
|
||||
}
|
||||
|
||||
private LiveClient self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
//TODO 弹幕发送队列
|
||||
|
||||
private BulletScreenEntity createBulletScreenEntity(String message) {
|
||||
return new BulletScreenEntity(
|
||||
getRoomIdOrShowRoomId(),
|
||||
@ -174,34 +201,27 @@ public class LiveClient {
|
||||
);
|
||||
}
|
||||
|
||||
public long getShowRoomId() {
|
||||
return showRoomId;
|
||||
}
|
||||
|
||||
public long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public Optional<LiveRoomInfoEntity.LiveRoom> getRoomInfo() {
|
||||
if (liveRoom == null) {
|
||||
try {
|
||||
liveRoom = fetchRoomInfo();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return Optional.of(liveRoom);
|
||||
public long getRoomIdOrShowRoomId() {
|
||||
return realRoomId != null ? realRoomId : showRoomId;
|
||||
}
|
||||
|
||||
public long getRoomIdOrShowRoomId() {
|
||||
return getRoomInfo().map(LiveRoomInfoEntity.LiveRoom::getRoomId).orElse(showRoomId);
|
||||
public long getShowRoomIdOrRoomId() {
|
||||
return showRoomId != null ? showRoomId : realRoomId;
|
||||
}
|
||||
|
||||
public int getBulletScreenLengthLimitOrDefaultLengthLimit() {
|
||||
return getRoomInfo().map(LiveRoomInfoEntity.LiveRoom::getMsgLength).orElse(BulletScreenConstDefinition.DEFAULT_MESSAGE_LENGTH_LIMIT);
|
||||
return liveRoom != null ? liveRoom.getMsgLength() : BulletScreenConstDefinition.DEFAULT_MESSAGE_LENGTH_LIMIT;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
private LiveClient self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -4,5 +4,9 @@ import com.hiczp.bilibili.api.live.socket.LiveClient;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
|
||||
public interface LiveClientProvider {
|
||||
LiveClient getLiveClient(EventLoopGroup eventLoopGroup, long showRoomId);
|
||||
LiveClient getLiveClient(EventLoopGroup eventLoopGroup, long roomId, boolean isRealRoomId);
|
||||
|
||||
default LiveClient getLiveClient(EventLoopGroup eventLoopGroup, long showRoomId) {
|
||||
return getLiveClient(eventLoopGroup, showRoomId, false);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import java.util.List;
|
||||
public class LiveClientTest {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LiveClientTest.class);
|
||||
private static final BilibiliAPI BILIBILI_API = Config.getBilibiliAPI();
|
||||
private static final long ROOM_ID = 102;
|
||||
private static final Config CONFIG = Config.getInstance();
|
||||
private static final long TEST_TIME = 70 * 1000;
|
||||
|
||||
@Ignore
|
||||
@ -28,7 +28,7 @@ public class LiveClientTest {
|
||||
public void _0_duplicateConnectAndCloseTest() throws Exception {
|
||||
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
LiveClient liveClient = BILIBILI_API
|
||||
.getLiveClient(eventLoopGroup, ROOM_ID);
|
||||
.getLiveClient(eventLoopGroup, CONFIG.getRoomId());
|
||||
LOGGER.debug("Connecting!");
|
||||
liveClient.connect();
|
||||
Thread.sleep(5000);
|
||||
@ -55,7 +55,7 @@ public class LiveClientTest {
|
||||
public void _1_longTimeTest() throws Exception {
|
||||
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
|
||||
LiveClient liveClient = BILIBILI_API
|
||||
.getLiveClient(eventLoopGroup, ROOM_ID)
|
||||
.getLiveClient(eventLoopGroup, CONFIG.getRoomId())
|
||||
.registerListener(new Listener());
|
||||
LOGGER.debug("Start long-time test");
|
||||
LOGGER.debug("Connecting!");
|
||||
|
Loading…
Reference in New Issue
Block a user