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

问题描述 投票:0回答:6

我正在尝试在 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());

  };

};
java android react-native okhttp
6个回答
11
投票

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

我能找到的唯一文档是this PR,其中有人添加了对此功能的支持(并打破了当前接受的答案)。当我尝试添加 PR 中记录的拦截器时,我遇到了与

CookieJar
相关的异常,我能够在 这个(未解决的🙄)问题中找到解决方案。

总长:

在与您的

MainApplication
相同的文件夹中添加一个名为
UserAgentInterceptor.java
的 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);
  }

}

然后在名为

UserAgentClientFactory.java
的同一文件夹中创建另一个 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

}

就是这样!


7
投票

所以我终于明白了。这是使用 React Native 覆盖

okhttp3
的 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 将使用的客户端。


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


3
投票

老问题,但我们在 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
方法调用的。

希望这有帮助!


0
投票

我已经使用 OkHttp 实现了此功能,我的代码与你的非常相似 - 并且一切正常。

考虑使用

addHeader("User-Agent", "Trevor")
而不是
header("User-Agent", "Trevor")
,因为后者将替换所有已设置的标题。

我使用

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

更新我也用

onCreate()
方法来做。一切都按其应有的方式进行。


0
投票

UserAgentInterceptor.java
添加到
MainApplication.java

的同一文件夹中
package your_package;
import your_package.BuildConfig;

import android.os.Build;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import android.util.Log;

public class UserAgentInterceptor implements Interceptor {
  public String useragent;

  public UserAgentInterceptor() {
    String versionName = BuildConfig.VERSION_NAME;
    int versionCode = BuildConfig.VERSION_CODE;

    String deviceName = Build.MODEL;
    String osVersion = Build.VERSION.RELEASE;

    this.useragent = String.format("dbk/%s/%d (device: %s; OS: Android %s)", versionName, versionCode, deviceName, osVersion);

    Log.d("UserAgentInterceptor", this.useragent);
  }

  @Override
  public Response intercept(Interceptor.Chain chain) throws IOException {
    Request originalRequest = chain.request();

    Request requestWithUserAgent = originalRequest.newBuilder()
      .removeHeader("User-Agent")
      .addHeader("User-Agent", useragent)
      .build();

    return chain.proceed(requestWithUserAgent);
  }

}

在同一文件夹中添加

CustomNetworkModule.java

package your_package;

import android.util.Log;

import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.ReactCookieJarContainer;
import java.util.concurrent.TimeUnit;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;


public class CustomNetworkModule implements OkHttpClientFactory {
    @Override
    public OkHttpClient createNewNetworkModuleClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        builder.writeTimeout(10, TimeUnit.SECONDS);
        builder.readTimeout(30, TimeUnit.SECONDS);
        builder.cookieJar(new ReactCookieJarContainer());
        builder.addInterceptor(new UserAgentInterceptor());

        return builder.build();
    }
}

并将其添加到

MainApplication.java

@Override
  public void onCreate() {
    super.onCreate();
    OkHttpClientProvider.setOkHttpClientFactory(new CustomNetworkModule());
    ...
  }
© www.soinside.com 2019 - 2024. All rights reserved.