11

我正在尝试User-Agent在 Android 上使用 React Native 设置。做了一些研究,看起来我应该使用okhttp Interceptor。我发现的一个示例解释了应该如何完成此操作(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());

  };

};
4

5 回答 5

9

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

我能找到的唯一文档是此 PR,其中有人添加了对此功能的支持(并打破了当前接受的答案)。当我尝试添加 PR 中记录的拦截器时,我遇到了一个异常CookieJar,我能够在这个(未解决的)问题中找到解决方案。

TLDR:

MainApplication在与您调用的文件夹相同的文件夹中添加一个 Java 类UserAgentInterceptor.java并将其放入其中:

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 类,UserAgentClientFactory.java并将其放入其中:

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方法中像这样注册工厂:

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

@Override
public void onCreate() {
  super.onCreate();

  OkHttpClientProvider.setOkHttpClientFactory(new UserAgentClientFactory());

  // Your other code stuffs

}

就是这样!

于 2021-02-11T21:28:25.210 回答
7

所以我终于想通了。这是okhttp3使用 React Native 覆盖 User-Agent 的解决方案。

创建一个名为CustomInterceptor.java

package com.trevor;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.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; 和覆盖该客户端,而不是创建香草OkHttpClient,因为这是 React Native 将使用的客户端。

于 2016-02-03T22:55:18.007 回答
5

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 的回答中的其他所有内容都对我有用。

于 2016-06-26T21:57:39.960 回答
2

Old issue, but we still ran into the same problem with React Native 0.59. This is what we did to fix (in Kotlin), as recent versions of okhttp prevent (and throw an exception) when trying to add an interceptor to an already initialized client:

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()
    }
}

This was done in a shared library between 2 apps, thus why we passed in the app name, version, and build number.

Usage from the app itself looked like:

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

This was called from the onCreate method in the main activity of the app.

Hope this helps!

于 2019-07-18T14:39:53.453 回答
0

我已经使用 OkHttp 实现了这个功能,我的代码和你的非常相似——一切都很好。

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

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

更新我也是用onCreate()方法做的。一切正常。

于 2016-02-01T08:28:48.310 回答