如何使用指定的POST参数打开Android浏览器?

28

在我的 Android 应用程序中,我需要在浏览器中打开一个链接。这个页面可以通过 POST 接收一些数据。我能否将这些参数(数据)添加到启动浏览器的意图(intent)中?

你知道这是否可行吗?如果可以,你能给我一些提示吗?


我能把这些参数(数据)添加到启动浏览器的意图中吗?使用POST方法可以吗?不行。使用GET方法可以。 - CommonsWare
谢谢。那么没有办法通过POST方式将一些数据发送到页面并在Android浏览器中打开它吗?即使我使用WebView? - Ungureanu Liviu
正确。就像您无法使用纯URL(例如Web页面中的超链接)在其他任何地方向页面提交数据一样,这也不是Android的特性--它是互联网的通用规则。 - CommonsWare
你说得对!我会寻找其他解决方案。谢谢! - Ungureanu Liviu
@UngureanuLiviu,你好,我想和你谈一下在Android中向POST请求添加参数的问题。 - Pankaj Nimgade
4个回答

14

使用 Webview:

WebView webview = new WebView(this);
setContentView(webview);
byte[] post = EncodingUtils.getBytes("postvariable=value&nextvar=value2", "BASE64");
webview.postUrl("http://www.geenie.nl/AnHeli/mobile/ranking/demo/index.php", post);

1
我该如何发送一个 JSON 负载? - user1796624

3

发送到浏览器的意图可以包含不仅仅是一个URL。在较旧版本的Android中,可以将额外的POST数据封装在意图中,但在更新版本中,这种能力已经消失了,但可以通过向发送到浏览器的意图中添加额外的标头数据来实现GET请求(可以是可表示为字符串的任何内容)。


当然,最终支持哪些内容取决于接收Intent的浏览器应用程序。 - Chris Stratton

2
try{
        String finalUrl = "javascript:" +
                "var to = 'http://the_link_you_want_to_open';" +
                "var p = {param1:'"+your_param+"',param2:'"+your_param+"'};" +
                "var myForm = document.createElement('form');" +
                "myForm.method='post' ;" +
                "myForm.action = to;" +
                "for (var k in p) {" +
                "var myInput = document.createElement('input') ;" +
                "myInput.setAttribute('type', 'text');" +
                "myInput.setAttribute('name', k) ;" +
                "myInput.setAttribute('value', p[k]);" +
                "myForm.appendChild(myInput) ;" +
                "}" +
                "document.body.appendChild(myForm) ;" +
                "myForm.submit() ;" +
                "document.body.removeChild(myForm) ;";


        Uri uriUrl = Uri.parse(finalUrl);
        Intent browserIntent = new Intent(Intent.ACTION_VIEW);
        PackageManager packageManager = this.getPackageManager();
        browserIntent.setData(uriUrl);
        List<ResolveInfo> list = packageManager.queryIntentActivities(browserIntent, 0);
        for (ResolveInfo resolveInfo : list) {
            String activityName = resolveInfo.activityInfo.name;
            if (activityName.contains("BrowserActivity")) {
                browserIntent =
                        packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName);
                ComponentName comp =
                        new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
                browserIntent.setAction(Intent.ACTION_VIEW);
                browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
                browserIntent.setComponent(comp);
                browserIntent.setData(uriUrl);
            }
        }

        this.startActivity(browserIntent);

    }catch (Exception e){
        e.printStackTrace();
        txtHeader.setText(e.toString());
    }

2
我已经尝试过了,但它不起作用。Chrome浏览器打开了,但没有任何反应。 - Highriser

0

我认为这个问题存在一些误解。缺少的是您需要POST而不是GET的目的。

如果您同意,我将做出一些在此情况下可能很常见的假设:

  • 您需要隐藏实际变量以避免被记录在历史中
  • 在用户获得控制之前,您需要与服务器进行一些交互
  • 您无法控制服务器本身,并且它使用(有意)POST请求

这些选项或要求中的任何一个都意味着需要进行一些额外的处理,这与通常的浏览器用例不同(其目的是提供完全控制处理和交互)。看起来您实际上正在寻求机器对机器(M2M)通信并最终输出HTML。

如果这是真的,那么使用一些OKHttp、HTTPURLConnection、Apache HTTP Client等是正确的选择。而不是通过Intent调用浏览器,后者几乎没有消息传递能力(只是点火并忘记 - 在http:...的情况下)。实际上需要对数据流进行一些分析(序列图可能有所帮助),然后将该过程工程化为M2M或辅助M2M交互。

如果您正在使用的服务器是您自己的,则为什么不创建一些REST/JSON/SOAP或其他M2M API来进行远程方法调用(RPC/RMI/...)呢?它并不像看起来那么复杂(例如:http://coreymaynard.com/blog/creating-a-restful-api-with-php/https://docs.phalconphp.com/pt/latest/reference/tutorial-rest.html)。
另一种选择是在您的应用程序服务器上进行M2M交互,因为这样可以反映BE服务器数据流的任何变化而无需更改应用程序。通过这种方式,您实际上部分地将M2M通信转移到了服务器端。
注意:使用应用程序与第三方服务器进行交互可能会产生一些法律影响。事实上,这些服务器可能不允许除浏览器(人类检测=验证码,User-Agent检测)以外的其他用途。在这种情况下,您必须与服务器所有者协商。

你可能使用POST的主要原因是请求不具有幂等性,但会改变某些内容。 - Flimm
1
虽然开头很有趣,但结尾几乎是误导性的。我们可以发布一些敏感数据,例如登录、密码、姓名、电话、令牌等,这些数据不应该在历史记录中显示,并且存在安全风险。但是我们必须传递它们以便从授权的Android应用程序授权访问网页。 - CoolMind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接