React Native& Android上的okhttp - 设置用户代理

时间:2016-01-31 21:34:31

标签: java android react-native okhttp okhttp3

我正在尝试在Android上使用React Native设置User-Agent。做了一些研究,看起来我应该使用okhttp 拦截器。我发现的一个例子解释了如何做到这一点(Link),但后来我不确定如何注册拦截器。

所以为了设置User-Agent我正在使用这个类:

public class CustomInterceptor implements Interceptor {
    @Override public Response intercept(Interceptor.Chain chain) throws IOException {
      Request originalRequest = chain.request();
      Request requestWithUserAgent = originalRequest.newBuilder()
          .removeHeader("User-Agent")
          .header("User-Agent", "Trevor")
          .build();
      return chain.proceed(requestWithUserAgent);
    }
}

那么剩下的就是注册上面的拦截器以便它应该在哪里完成?也许在MainActivity.java

OkHttpClient okHttp = new OkHttpClient();
okHttp.interceptors().add(new CustomInterceptor());

构建应用时我没有遇到任何错误,所以我认为CustomInterceptor应该没问题 - 只需要让应用使用它。

更新: 我目前正在尝试在MainActivity中注册拦截器,但它不会接受它:

public class MainActivity extends ReactActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    OkHttpClient client = new OkHttpClient();
    client.networkInterceptors().add(new CustomInterceptor());

  };

};

5 个答案:

答案 0 :(得分:6)

React Native的迭代速度非常快,以至于接受的答案对我不起作用。

对于RN 0.27.2,我必须在CustomInterceptor中导入okhttp3.OkHttpClient并更改MainActivity中的attachInterceptor()方法以替换客户端。

private void attachInterceptor() {
    OkHttpClient currentClient = OkHttpClientProvider.getOkHttpClient();
    OkHttpClient replacementClient = currentClient.newBuilder().addNetworkInterceptor(new CustomInterceptor()).build();
    OkHttpClientProvider.replaceOkHttpClient(replacementClient);
}

ekonstantinidis的所有其他答案对我有用。

答案 1 :(得分:6)

这里的所有答案都不适用于 RN 0.63.2。我能够让它工作,并且在我的研究中能够找到(尽管非常稀缺)支持此功能的文档。

我能找到的唯一文档是 this PR,其中有人添加了对此功能的支持(并破坏了当前接受的答案)。当我尝试添加 PR 中记录的拦截器时,我遇到了与 json.dumps 相关的异常,我能够在 this (unresolved ?) issue 中找到解决方案。

TLDR:

在与您的 CookieJar 相同的文件夹中添加一个名为 MainApplication 的 Java 类并将其放入其中:

UserAgentInterceptor

然后在名为 package YOUR.PACKAGE.NAME; // <-- REPLACE ME import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; import java.io.IOException; public class UserAgentInterceptor implements Interceptor { public UserAgentInterceptor() {} @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request originalRequest = chain.request(); Request requestWithUserAgent = originalRequest.newBuilder() .removeHeader("User-Agent") .addHeader("User-Agent", "YOUR USER AGENT") // <-- REPLACE ME .build(); return chain.proceed(requestWithUserAgent); } } 的同一文件夹中创建另一个 Java 类并将其放入其中:

UserAgentClientFactor

然后在您的 package YOUR.PACKAGE.NAME; // <-- REPLACE ME import com.facebook.react.modules.network.OkHttpClientFactory; import com.facebook.react.modules.network.ReactCookieJarContainer; import okhttp3.OkHttpClient; public class UserAgentClientFactory implements OkHttpClientFactory { public OkHttpClient createNewNetworkModuleClient() { return new OkHttpClient.Builder() .cookieJar(new ReactCookieJarContainer()) .addInterceptor(new UserAgentInterceptor()) .build(); } } MainApplication 方法中像这样注册工厂:

onCreate

就是这样!

答案 2 :(得分:4)

所以我终于明白了。以下是使用React Native覆盖okhttp的User-Agent的解决方案。

创建名为CustomInterceptor.java的文件:

package com.trevor;

import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.IOException;

public class CustomInterceptor implements Interceptor {

    public CustomInterceptor() {}

    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request requestWithUserAgent = originalRequest.newBuilder()
            .removeHeader("User-Agent")
            .addHeader("User-Agent", "Trevor")
            .build();

        return chain.proceed(requestWithUserAgent);
    }

}

然后在MainActivity.java 覆盖 onCreate方法:

...
import com.facebook.react.modules.network.OkHttpClientProvider;
...

public class MainActivity extends ReactActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        attachInterceptor();
    }

    private void attachInterceptor() {
        OkHttpClient client = OkHttpClientProvider.getOkHttpClient();
        client.networkInterceptors().add(new CustomInterceptor());
    }
}

请注意,我正在导入com.facebook.react.modules.network.OkHttpClientProvider; 并覆盖该客户端,而不是创建一个vanilla OkHttpClient,因为这是React Native将使用的那个。

答案 3 :(得分:0)

我使用OkHttp实现了这个功能,我的代码与你的代码非常相似 - 一切正常。

考虑使用addHeader("User-Agent", "Trevor")代替header("User-Agent", "Trevor"),因为后者将替换所有已设置的标头。

我正在使用okHttp.networkInterceptors().add(new CustomInterceptor());代替okHttp.interceptors().add(new CustomInterceptor());,但我不认为这是一个值得关注的问题。

更新我也是在onCreate()方法中执行此操作。一切都按预期工作。

答案 4 :(得分:0)

旧问题,但我们仍然遇到React Native 0.59的相同问题。这是我们(在Kotlin中)所做的修复,因为okhttp的最新版本在尝试向已初始化的客户端添加拦截器时会阻止(并引发异常):

import android.os.Build
import com.facebook.react.modules.network.OkHttpClientFactory
import com.jaredrummler.android.device.DeviceName
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response

class UserAgentInterceptor(val userAgent: String): Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()

        val correctRequest = originalRequest.newBuilder()
                .removeHeader("User-Agent")
                .addHeader("User-Agent", userAgent)
                .build()
        return chain.proceed(correctRequest)
    }
}

class UserAgentClientFactory(val appName: String, val appVersion: String, val buildNumber: String): OkHttpClientFactory {
    private fun userAgentValue(): String {
        val deviceName = DeviceName.getDeviceName()
        val osVersion = Build.VERSION.RELEASE
        return "$appName/$appVersion (build: $buildNumber; device: $deviceName; OS: Android $osVersion)"
    }

    override fun createNewNetworkModuleClient(): OkHttpClient {
        val builder = com.facebook.react.modules.network.OkHttpClientProvider.createClientBuilder()
        return builder.addInterceptor(UserAgentInterceptor(userAgent = userAgentValue())).build()
    }
}

这是在2个应用程序之间的共享库中完成的,因此我们传入了应用程序名称,版本和内部版本号。

应用本身的使用方式如下:

private fun configureUserAgent() {
    val versionName = BuildConfig.VERSION_NAME
    val versionCode = BuildConfig.VERSION_CODE
    OkHttpClientProvider.setOkHttpClientFactory(UserAgentClientFactory(appName = "My App", appVersion = versionName, buildNumber = "$versionCode"))
}

在应用程序的主要活动中,该方法是通过onCreate方法调用的。

希望这会有所帮助!