diff --git a/README.md b/README.md index 050b5ae..8a07eda 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ CaptchaMismatchException 在验证码不正确时抛出, 见下文 [验证码问 login 方法的返回值为 LoginResponseEntity 类型, 使用 - loginResponseEntity.toBilibiliAccount() + BilibiliAccount bilibiliAccount = loginResponseEntity.toBilibiliAccount(); 来获得一个 BilibiliAccount 实例, 其中包含了 OAuth2 的用户凭证, 如果有需要, 可以将其持久化保存. @@ -67,6 +67,10 @@ IOException 在网络故障时抛出 LoginException 在 token 错误,或者 refreshToken 错误或过期时抛出. +refreshToken 操作在正常情况下将在服务器返回 401(实际上 B站 不用 401 来表示未登录)时自动进行, 因此 BilibiliAPI 内部持有的 BilibiliAccount 的实例的内容可能会发生改变, 如果需要在应用关闭时持久化用户 token, 需要这样来取得最后的 BilibiliAccount 状态 + + BilibiliAccount bilibiliAccount = bilibiliAPI.getBilibiliAccount(); + ### 登出 bilibiliAPI.logout(); @@ -166,6 +170,37 @@ B站客户端内置的 WebView 就是通过这种方式来工作的(WebView 访 如果想跟 B站 客户端一样弄一个什么内嵌 WebView 的话, 这个 API 就可以派上用场(只需要在 WebView 初始化完毕后让 WebView 去访问这个 url, 就登陆了)(goUrl 可以是任意值, 全部的 302 重定向完成后将进入这个地址). +### Web API +上文讲到, 通过 SSO API, 可以将 token 转为 cookie, 在本项目中, Web API 封装在 BilibiliWebAPI 中, 可以通过如下方式得到一个已经登录了的 BilibiliWebAPI 实例 + + String username = "yourUsername"; + String password = "yourPassword"; + BilibiliAPI bilibiliAPI = new BilibiliAPI(); + bilibiliAPI.login(String username, String password); + BilibiliWebAPI bilibiliWebAPI = bilibiliAPI.getBilibiliWebAPI(); + +IOException 在网络错误时抛出(获取 cookie 时需要进行网络请求) + +如果将之前的 bilibiliAPI.toCookies() 的返回值(cookiesMap)持久化了下来的话, 下次可以通过以下方式直接获得一个已经登录了的 BilibiliWebAPI 实例(注意, cookie 没有 refreshToken 机制, 过期不会自动刷新, 因此不推荐持久化 cookie) + + Map> cookiesMap = bilibiliAPI.toCookies(); + //序列化后存储 + //... + //反序列化后得到上次存储的 cookiesMap + BilibiliWebAPI bilibiliWebAPI = new BilibiliWebAPI(cookiesMap); + +有了 BilibiliWebAPI 实例之后, 通过类似以下代码的形式来获取对应的 Service, API 调用方法和基于 Token 方式的 API 一致 + + LiveService liveService = bilibiliWebAPI.getLiveService(); + +(这个 LiveService 是 Web API 里的 LiveService) + +由于 Web API 是有状态的, 每个 BilibiliWebAPI 内部维护的 CookieJar 是同一个, 一些验证有关的 API 可能会改变 cookie. + +通过以下代码来获得一个 BilibiliWebAPI 中目前持有的 CookieJar 的引用 + + bilibiliWebAPI.getCookieJar(); + ### API 调用示例 打印一个直播间的历史弹幕 diff --git a/src/main/java/com/hiczp/bilibili/api/web/BilibiliWebAPI.java b/src/main/java/com/hiczp/bilibili/api/web/BilibiliWebAPI.java index d5a6f89..b3b0cfc 100644 --- a/src/main/java/com/hiczp/bilibili/api/web/BilibiliWebAPI.java +++ b/src/main/java/com/hiczp/bilibili/api/web/BilibiliWebAPI.java @@ -18,17 +18,17 @@ import java.util.Map; public class BilibiliWebAPI { private final BrowserProperties browserProperties; - private final SimpleCookieJar simpleCookieJar; + private final SimpleCookieJar cookieJar; private LiveService liveService; - public BilibiliWebAPI(BrowserProperties browserProperties, SimpleCookieJar simpleCookieJar) { + public BilibiliWebAPI(BrowserProperties browserProperties, SimpleCookieJar cookieJar) { this.browserProperties = browserProperties; - this.simpleCookieJar = simpleCookieJar; + this.cookieJar = cookieJar; } - public BilibiliWebAPI(SimpleCookieJar simpleCookieJar) { - this(BrowserProperties.defaultSetting(), simpleCookieJar); + public BilibiliWebAPI(SimpleCookieJar cookieJar) { + this(BrowserProperties.defaultSetting(), cookieJar); } public BilibiliWebAPI(BrowserProperties browserProperties, Map> cookiesMap) { @@ -50,7 +50,7 @@ public class BilibiliWebAPI { OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); okHttpClientBuilder - .cookieJar(simpleCookieJar) + .cookieJar(cookieJar) .addInterceptor(new AddFixedHeadersInterceptor( "User-Agent", browserProperties.getUserAgent() )); @@ -68,7 +68,7 @@ public class BilibiliWebAPI { .create(LiveService.class); } - public SimpleCookieJar getSimpleCookieJar() { - return simpleCookieJar; + public SimpleCookieJar getCookieJar() { + return cookieJar; } } diff --git a/src/main/java/com/hiczp/bilibili/api/web/cookie/SimpleCookieJar.java b/src/main/java/com/hiczp/bilibili/api/web/cookie/SimpleCookieJar.java index 7c29070..c655da3 100644 --- a/src/main/java/com/hiczp/bilibili/api/web/cookie/SimpleCookieJar.java +++ b/src/main/java/com/hiczp/bilibili/api/web/cookie/SimpleCookieJar.java @@ -5,20 +5,20 @@ import okhttp3.CookieJar; import okhttp3.HttpUrl; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class SimpleCookieJar implements CookieJar { private Map> cookiesMap; public SimpleCookieJar() { - cookiesMap = new HashMap<>(); + cookiesMap = new ConcurrentHashMap<>(); } public SimpleCookieJar(Map> cookiesMap) { - this.cookiesMap = new HashMap<>(cookiesMap); + this.cookiesMap = new ConcurrentHashMap<>(cookiesMap); } @Override