如何从Android应用程序修改HTTP请求头?

如何从Android应用程序修改HTTP请求头?,android,http,Android,Http,我有没有办法捕获从我的应用程序发送的所有HTTP请求,并在发送之前修改它们的头文件?我想修改它们的referer头,这样发送请求的服务器就会认为它们来自web浏览器而不是移动应用程序。谢谢大家! 更新:为了给您提供更多的上下文,我计划使用Phonegap将chrome扩展移植到Android应用程序中。有些允许在PC上播放的YouTube视频不允许在手机上播放,我怀疑这是因为嵌入android应用程序中的YouTube播放器没有推荐人标题。我正在试图找到解决此问题的方法,以便我也可以在手机上播放

我有没有办法捕获从我的应用程序发送的所有HTTP请求,并在发送之前修改它们的头文件?我想修改它们的
referer
头,这样发送请求的服务器就会认为它们来自web浏览器而不是移动应用程序。谢谢大家!


更新:为了给您提供更多的上下文,我计划使用Phonegap将chrome扩展移植到Android应用程序中。有些允许在PC上播放的YouTube视频不允许在手机上播放,我怀疑这是因为嵌入android应用程序中的YouTube播放器没有推荐人标题。我正在试图找到解决此问题的方法,以便我也可以在手机上播放此类视频。

您可以很容易地设置标题,如下所示:

            final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36";
            final String URL = "http://www.cnn.com";
            final String REFERER_URL = "http://www.w3.org/hypertext/DataSources/Overview.html";

            HttpClient httpclient = new DefaultHttpClient();
            HttpGet request = new HttpGet(URL);

            // add request header
            request.addHeader("User-Agent", USER_AGENT);
            request.addHeader("Referer", REFERER_URL);

            try {
                HttpResponse response = httpclient.execute(request);
            } catch (Exception e) {
                // ...
            }
我还添加了“用户代理”,因为大多数网站都使用它而不是“Referer”来确定客户端是否是移动浏览器


请注意,“Referer”拼写错误;这在我的代码中是故意的。看见我猜这是多年前的一个拼写错误,只是卡住了。

免责声明:肮脏黑客,仅在Android 4.4上测试,但应适用于Android 4.0及以上版本

需要尽早调用setupURLStreamHandlerFactory()方法,并使用
URL.setURLStreamHandlerFactory()
设置我们自己的URL流处理程序工厂。工厂用于通过
URL.openConnection()
打开的所有连接。我们为所有人设置了一个特殊的处理程序http://... 在创建的HttpUrlConnection上设置“Referer”头的URL

private static String REFERER_URL = "http://www.example.com/referer";

private void setupURLStreamHandlerFactory() {
    URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
        @Override
        public URLStreamHandler createURLStreamHandler(String protocol) {
            if ("http".equals(protocol)) {
                try {
                    String className = Build.VERSION.SDK_INT < 19 ?  "libcore.net.http.HttpHandler" : "com.android.okhttp.HttpHandler";
                    URLStreamHandler streamHandler = (URLStreamHandler) Class
                            .forName(className).newInstance();
                    return wrap(streamHandler);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        }
    });
}

private static URLStreamHandler wrap(final URLStreamHandler streamHandler) {
    return new URLStreamHandler() {
        @Override
        protected URLConnection openConnection(URL u) throws IOException {
            URLConnection conn;
            try {
                Method openConnectionMethod = URLStreamHandler.class
                        .getDeclaredMethod("openConnection", URL.class);
                openConnectionMethod.setAccessible(true);
                conn = (URLConnection) openConnectionMethod.invoke(
                        streamHandler, u);
                conn.setRequestProperty("Referer", REFERER_URL);
                return conn;
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                if (e.getTargetException() instanceof IOException) {
                    throw (IOException) e.getTargetException();
                } else {
                    throw new RuntimeException(e);
                }
            }
        }
    };
}
private static String REFERER\u URL=”http://www.example.com/referer";
私有void setupURLStreamHandlerFactory(){
setURLStreamHandlerFactory(新的URLStreamHandlerFactory(){
@凌驾
公共URLStreamHandler createURLStreamHandler(字符串协议){
如果(“http”.equals(协议)){
试一试{
字符串className=Build.VERSION.SDK_INT<19?“libcore.net.http.HttpHandler”:“com.android.okhttp.HttpHandler”;
URLStreamHandler streamHandler=(URLStreamHandler)类
.forName(className).newInstance();
返回包装(streamHandler);
}捕获(例外e){
抛出新的运行时异常(e);
}
}
返回null;
}
});
}
私有静态URLStreamHandler包装(最终URLStreamHandler streamHandler){
返回新的URLStreamHandler(){
@凌驾
受保护的URL连接openConnection(URL u)引发IOException{
连接连接;
试一试{
方法openConnectionMethod=URLStreamHandler.class
.getDeclaredMethod(“openConnection”,URL.class);
openConnectionMethod.setAccessible(true);
conn=(URLConnection)openConnectionMethod.invoke(
streamHandler,u);
conn.setRequestProperty(“Referer”,Referer\u URL);
返回连接;
}捕获(无此方法例外){
抛出新的运行时异常(e);
}捕获(非法访问例外e){
抛出新的运行时异常(e);
}捕获(IllegalArgumentException e){
抛出新的运行时异常(e);
}捕获(调用TargetException e){
if(例如getTargetException()实例IOException){
抛出(IOException)e.getTargetException();
}否则{
抛出新的运行时异常(e);
}
}
}
};
}

编辑:修改为适用于Android 4.4 Kitkat之前的版本

Youtube检测用户浏览器的
代理字符串
,其中包含有关浏览器的信息。如果要使用
WebView
来显示youtube视频,则可以设置
WebView
代理字符串。
您可以在internet上找到不同浏览器的代理字符串。我在这里找到了一些:

以下是我如何通过模拟Firefox浏览器播放Bob Marley的歌曲,这是手机上不允许播放的歌曲:

package com.my.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

    public class MyActivity extends Activity {

        private WebView mWebView ;

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

            mWebView  = new WebView(this);
            // Enable javascript
            mWebView.getSettings().setJavaScriptEnabled(true);
            // Impersonate Mozzila browser
            mWebView.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:21.0.0) Gecko/20121011 Firefox/21.0.0");
            final Activity activity = this;

            mWebView.setWebViewClient(new WebViewClient() {
                public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                    Toast.makeText(activity, description, Toast.LENGTH_SHORT).show();
                }
            });

            mWebView .loadUrl("http://youtube.com/watch?v=x59kS2AOrGM");
            setContentView(mWebView);
        }

    }
编辑:

您还需要为您的活动授予使用internet的权限,方法是将此行添加到您的
AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" /> 


问题是我自己没有创建请求对象。请求是从我的应用程序使用的外部API发送的,因此我必须侦听所有传出的HTTP请求,并在发送它们之前修改它们的头。这可以通过chrome app/extensions中的
chrome.webRequest.beforeSend(function()…)
实现,但我想知道如何在Android中实现相同的功能:)简单地说,你不能。你唯一的选择是创建一个中间人HTTP代理,这在移动设备上不是一个好主意。我想相信一定有办法?可能使用
BroadcastReceiver
?您是否考虑过使用HttpRequestInterceptor-()@Vino如果我没有一个
request
对象可以专门引用,这个方法似乎不可能。一个肮脏的黑客可以吗?或者您正在寻找一个干净的解决方案?@MaximusS您是否可以访问库的源代码(至少通过反编译)?一个可能会起作用的坏方法是找到
DefaultHttpClient
的初始化位置,然后向其中添加
HttpRequestInterceptor
(必要时通过反射)。然而,在不知道它是哪个库的情况下,很难知道确切的步骤(或者即使可能)。该库实际上是Youtube的IFrame player API,它向Youtube服务器发送请求以获取视频数据。这是一个非常聪明的把戏!然而,它只在KitKat起作用,不是吗?我认为OkHttp以前不存在。我对代码做了一点修改,所以它应该存在