2014-06-23 66 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

嗨汉斯!我非常感激。你能否阅读我的更新,看看你的黑客能否适用于我的情况? –