Как изменить заголовки HTTP-запросов из приложения Android?

Есть ли способ захватить все HTTP-запросы, отправляемые из моего приложения, и изменить их заголовки до их отправки? Я хочу изменить их заголовок referer, чтобы сервер, на который были отправлены запросы, думал, как будто они поступают из веб-браузера, а не из мобильного приложения. Спасибо!

Обновление:. Чтобы предоставить вам больше контекста, я планирую переносить расширение chrome Instant Music в Android приложение с помощью Phonegap. Некоторые видеоролики YouTube, разрешенные на ПК, запрещены на мобильных устройствах, и я подозреваю, что, поскольку проигрыватель YouTube, встроенный в приложение для Android, не имеет заголовка реферера. Я пытаюсь найти решение этой проблемы, чтобы я мог воспроизводить такие видео на мобильных устройствах.

Ответ 1

Youtube обнаруживает браузер пользователя Agent String, который содержит информацию о браузере. Если бы вы использовали WebView для показа видео YouTube, тогда можно было бы установить это WebView Agent String. Вы можете найти строки операторов разных браузеров в Интернете. Я нашел здесь: Строки агента.

Вот как я играю песню Боба Марли, которая не разрешена на мобильных телефонах, олицетворяя браузер Firefox:

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

    }

ИЗМЕНИТЬ:

Вам также необходимо предоставить разрешение для своей деятельности использовать Интернет, добавив эту строку в свой AndroidManifest.xml:

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

Ответ 2

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Грязный взлом, протестированный только на Android 4.4, но должен работать на Android 4.0 и выше.

Методы setupURLStreamHandlerFactory() должны быть вызваны как можно раньше и установите наш собственный обработчик потока URL factory с помощью URL.setURLStreamHandlerFactory(). factory используется для всех подключений, открытых через URL.openConnection(). Мы создали специальный обработчик для всех URL http://..., которые задают заголовок "Referer" на созданном HttpUrlConnection.

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

РЕДАКТИРОВАТЬ: Изменено для работы с версиями до Android 4.4 Kitkat, а также

Ответ 3

Вы можете легко настроить заголовок следующим образом:

            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) {
                // ...
            }

Я добавил "User-Agent", так как большинство сайтов используют это, а не "Referer", чтобы определить, является ли клиент мобильным браузером или нет.

Обратите внимание, что "Referer" имеет орфографическую ошибку; это намеренно в моем коде. См. эту ссылку. Угадай, что это была опечатка много лет назад и просто застряла.