2014-06-23 96 views
12

有沒有辦法讓我捕獲從我的應用發送的所有HTTP請求,並在發送之前修改它們的頭部?我想修改它們的referer標頭,以便請求發送到的服務器認爲它們來自Web瀏覽器而不是移動應用程序。謝謝!如何修改Android應用程序的HTTP請求標頭?

更新:爲了給您更多的上下文,我計劃使用Phonegap將chrome擴展Instant Music移植到Android應用程序中。某些允許在PC上播放的YouTube視頻不允許在手機上播放,我懷疑這是因爲嵌入到android應用中的YouTube播放器沒有引用標頭。我正試圖找到解決這個問題的方法,以便我可以在手機上播放這些視頻。

+0

是一個骯髒的黑客行嗎?或者你正在尋找一個乾淨的解決方案? –

+0

骯髒的黑客很好。 –

+0

@MaximusS你有權訪問圖書館的源代碼(至少是通過反編譯)嗎?一個可以工作的骯髒的黑客就是找到'DefaultHttpClient'被初始化的地方,然後添加一個'HttpRequestInterceptor'(如果需要,通過反射)。然而,很難知道確切的步驟(或者即使有可能),但不知道它是哪個庫。 – matiash

回答

8

的Youtube用戶檢測瀏覽器的Agent String其中包含有關瀏覽器的信息。如果您要使用WebView來顯示YouTube視頻,則可以設置WebViewAgent String。 您可以在互聯網上找到不同瀏覽器的代理字符串。我在這裏找到了一些:Agent Strings

下面是如何通過模仿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" /> 
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) { 
       // ... 
      } 

我補充說:「用戶代理」爲好,因爲大多數網站使用,而不是「引薦」,以確定是否客戶端是一個手機瀏覽器或不。

請注意,「Referer」拼寫錯誤;這是我的代碼中的故意。見this link。猜測這是多年前的一個錯字,只是卡住了。

+0

問題是我沒有自己提出請求對象。這些請求是從我的應用程序使用的外部API發送的,因此,我必須監聽所有傳出的HTTP請求,並在發送之前修改它們的標頭。這可以通過Chrome應用程序/擴展中的'chrome.webRequest.beforeSend(function()..)'來完成,但是我想知道如何在Android中實現相同的功能:) –

+0

簡而言之,你不能。你唯一的選擇是創建一箇中間人HTTP代理,這在移動設備上並不是一個好主意。 –

+0

我想相信一定有辦法嗎?也許使用'BroadcastReceiver'? –

5

免責聲明:骯髒的黑客攻擊,只在Android 4.4上測試過,但應該適用於Android 4.0及更高版本。

需要儘早調用setupURLStreamHandlerFactory()方法,並使用URL.setURLStreamHandlerFactory()設置我們自己的URL流處理程序工廠。工廠用於通過URL.openConnection()打開的所有連接。我們爲所有http:// ... URL設置了一個特殊的處理程序,它在創建的HttpUrlConnection上設置了'Referer'標題。

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奇巧的工作以及

+0

這是一個非常聰明的把戲!但它只會在KitKat中工作,不是嗎?我不認爲OkHttp以前出現過。 – matiash

+0

我改變了一下代碼,所以它也適用於以前的版本。 –

+0

嗨漢斯!我非常感激。你能否閱讀我的更新,看看你的黑客能否適用於我的情況? –