为了得到我的瓷砖,我这样做:
style(styleUri = Style.MAPBOX_STREETS) {
+vectorSource(id = "parcel-source") {
url("http://example.com/{z}/{x}/{y}.png")
}
但是我需要向图块提供商提供一个令牌,并带有像
Authorization: bearer [token]
这样的 HTTP 标头。
文档展示了HTTP拦截器的框架,但没有提供关于如何实现要实现的接口的5个功能的线索。 我在API参考中也找不到涉及的接口。 有一个针对类似问题的开放问题已记录。
此外,适用于 v9.5 的解决方案 在 v10 中似乎不再可用(HttpRequestUtil 缺失)。
@MapboxModule(type = CommonHttpClient)
class CustomMapboxOkHttpService : HttpServiceInterface {
val map = MapboxOkHttpService()
override fun setInterceptor(interceptor: HttpServiceInterceptorInterface?) {
map.setInterceptor(interceptor)
}
override fun setMaxRequestsPerHost(max: Byte) {
map.setMaxRequestsPerHost(max)
}
override fun request(request: HttpRequest, callback: HttpResponseCallback): Long {
token?.let {
request.headers["Authorization"] = "Bearer $it"
}
return map.request(request, callback)
}
override fun cancelRequest(id: Long, callback: ResultCallback) {
map.cancelRequest(id, callback)
}
override fun supportsKeepCompression(): Boolean {
return map.supportsKeepCompression()
}
override fun download(options: DownloadOptions, callback: DownloadStatusCallback): Long {
return map.download(options, callback)
}
companion object {
var token: String? = null
}
}
请勿排除文档中所述的公共库
为了临时解决这个问题,我在java中使用了一个简单的概念,如果你提供相同的包结构,你可以替换特定的类
所以我做了以下事情:
/**
copied from mapbox sdk with minor updates
*/
class LazyClient {
private final SocketFactory socketFactory;
private final boolean disableHttp2;
private byte maxRequestsPerHost = 0;
private static final long DEFAULT_CONNECT_TIMEOUT_SEC = 30;
private static final long DEFAULT_READ_TIMEOUT_SEC = 60;
private volatile OkHttpClient client;
private boolean shouldEnablePinning = isPinningEnabled();
LazyClient(@Nullable SocketFactory socketFactory, boolean disableHttp2) {
this.socketFactory = socketFactory;
this.disableHttp2 = disableHttp2;
}
OkHttpClient get() {
if (client == null) {
synchronized (this) {
if (client == null) {
client = buildOkHttpClient(socketFactory, disableHttp2);
assert client != null;
if (maxRequestsPerHost != 0) {
client.dispatcher().setMaxRequestsPerHost(maxRequestsPerHost);
}
}
}
}
return client;
}
synchronized void setMaxRequestsPerHost(byte max) {
maxRequestsPerHost = max;
if (maxRequestsPerHost != 0) {
synchronized (this) {
OkHttpClient client = this.client;
if (client != null) {
client.dispatcher().setMaxRequestsPerHost(max);
}
}
}
}
private static OkHttpClient buildOkHttpClient(@Nullable SocketFactory socketFactory, boolean disableHttp2) {
OkHttpClient.Builder builder =
CommonOkHttp.INSTANCE.builder()
//new OkHttpClient.Builder()
.eventListenerFactory(NetworkUsageListener.FACTORY)
.connectTimeout(DEFAULT_CONNECT_TIMEOUT_SEC, TimeUnit.SECONDS)
.readTimeout(DEFAULT_READ_TIMEOUT_SEC, TimeUnit.SECONDS)
.addNetworkInterceptor(new CustomInterceptor());
if(isPinningEnabled()){
builder.certificatePinner(certPinner);
}
if (socketFactory != null) {
builder.socketFactory(socketFactory);
}
if (disableHttp2) {
// TODO: We are forcing HTTP1.1 since we are getting the following exception for download task for big files with HTTP2:
// "okhttp3.internal.http2.StreamResetException: stream was reset: PROTOCOL_ERROR"
builder.protocols(Arrays.asList(Protocol.HTTP_1_1));
}
return builder.build();
}
HttpServiceInterface
方法时遇到了 这个问题
。 在 v10 中,还有另一个使用
HttpServiceFactory.getInstance().setInterceptor
的选项。这个接口实现起来要简单得多,并且每个方法都应该返回相同的对象。这是我的方法:
class CustomMapboxIntercepter() : HttpServiceInterceptorInterface {
override fun onRequest(request: HttpRequest): HttpRequest {
request.headers["Authorization"] = "Bearer $token"
return request
}
override fun onDownload(download: DownloadOptions): DownloadOptions {
return download
}
override fun onResponse(response: HttpResponse): HttpResponse {
return response
}
}
然后只需根据类设置拦截器即可:
HttpServiceFactory.getInstance().setIntercepter(CustomMapboxIntercepter())
这种方法还可以轻松地在构造函数中添加参数。
似乎在 v11 中也是可能的,但对 API 做了一些小改动:
将 HttpServiceFactory.getInstance().setInterceptor 替换为 HttpServiceFactory.setHttpServiceInterceptor。