http请求到WD电视

时间:2017-01-10 15:21:13

标签: java android curl

我试图为Android应用程序编写一种控制WD电视的方法。 在我的终端上的linux中,我这样做,它完美地工作: curl -s -d' {" remote":" n"}' -v http://192.168.0.3/cgi-bin/toServerValue.cgi

{" remote":" n"}是为OK按钮发送的json参数。

到目前为止,这是我的java代码:

   try {
   String url="192.168.0.3/cgi-bin/toServerValue.cgi";
        URL object=new URL(url);

        HttpURLConnection con = (HttpURLConnection) object.openConnection();
        con.setDoOutput(true);
        con.setDoInput(true);
        con.setRequestProperty("Content-Type", application/json;charset=UTF-8");
        con.setRequestMethod("POST");

        JSONObject wd=new JSONObject();
        wd.put("remote", "n");

        OutputStreamWriter wr= new OutputStreamWriter(con.getOutputStream());
        wr.write(wd.toString());
        wr.flush();
        con.disconnect();


    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }

thx求助

当我使用http://

时,这是logcat
D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
I/System.out: (HTTPLog)-Static: SBServiceAPI: getService class android.os.ServiceManager
I/System.out: (HTTPLog)-Static: isShipBuild true
I/System.out: (HTTPLog)-Thread-1-928574752: SmartBonding Enabling is true, SHIP_BUILD is true, log to file is false, DBG is false
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
          Process: net.tchouny.httppost, PID: 20138
          java.lang.IllegalStateException: Could not execute method for android:onClick
              at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
              at android.view.View.performClick(View.java:5156)
              at android.view.View$PerformClick.run(View.java:20755)
              at android.os.Handler.handleCallback(Handler.java:739)
              at android.os.Handler.dispatchMessage(Handler.java:95)
              at android.os.Looper.loop(Looper.java:145)
              at android.app.ActivityThread.main(ActivityThread.java:5832)
              at java.lang.reflect.Method.invoke(Native Method)
              at java.lang.reflect.Method.invoke(Method.java:372)
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
           Caused by: java.lang.reflect.InvocationTargetException
              at java.lang.reflect.Method.invoke(Native Method)
              at java.lang.reflect.Method.invoke(Method.java:372)
              at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
              at android.view.View.performClick(View.java:5156) 
              at android.view.View$PerformClick.run(View.java:20755) 
              at android.os.Handler.handleCallback(Handler.java:739) 
              at android.os.Handler.dispatchMessage(Handler.java:95) 
              at android.os.Looper.loop(Looper.java:145) 
              at android.app.ActivityThread.main(ActivityThread.java:5832) 
              at java.lang.reflect.Method.invoke(Native Method) 
              at java.lang.reflect.Method.invoke(Method.java:372) 
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
           Caused by: android.os.NetworkOnMainThreadException
              at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
              at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:110)
              at libcore.io.IoBridge.connectErrno(IoBridge.java:137)
              at libcore.io.IoBridge.connect(IoBridge.java:122)
              at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
              at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:456)
              at java.net.Socket.connect(Socket.java:882)
              at com.android.okhttp.internal.Platform.connectSocket(Platform.java:139)
              at com.android.okhttp.Connection.connect(Connection.java:1171)
              at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:380)
              at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:289)
              at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:373)
              at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:106)
              at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:208)
              at net.tchouny.httppost.MainActivity.httpPost(MainActivity.java:48)
              at java.lang.reflect.Method.invoke(Native Method) 
              at java.lang.reflect.Method.invoke(Method.java:372) 
              at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
              at android.view.View.performClick(View.java:5156) 
              at android.view.View$PerformClick.run(View.java:20755) 
              at android.os.Handler.handleCallback(Handler.java:739) 
              at android.os.Handler.dispatchMessage(Handler.java:95) 
              at android.os.Looper.loop(Looper.java:145) 
              at android.app.ActivityThread.main(ActivityThread.java:5832) 
              at java.lang.reflect.Method.invoke(Native Method) 
              at java.lang.reflect.Method.invoke(Method.java:372) 
              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

它不起作用。 这就是我现在所做的:

public class MainActivity extends AppCompatActivity {

private static final String wdURL = "http://192.168.0.3/cgi-bin/toServerValue.cgi";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

}

       private void sendCommand(final String command) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    URL object=new URL(wdURL);

                    HttpURLConnection con = (HttpURLConnection) object.openConnection();
                    con.setDoOutput(true);
                    con.setRequestProperty("Content-Type", "text/html;charset=iso-8859-1");
                    con.setRequestMethod("POST");


                    JSONObject wd =new JSONObject();
                    wd.put("remote", command);

                    OutputStreamWriter wr= new OutputStreamWriter(con.getOutputStream());
                    wr.write(wd.toString());
                    wr.flush();
                    con.disconnect();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

public void httpPost (View v){
    sendCommand("w");

}
}

这是logcat:

01-11 09:52:41.686 28555-28555/? E/Zygote: MountEmulatedStorage()
01-11 09:52:41.686 28555-28555/? E/Zygote: v2
01-11 09:52:41.686 28555-28555/? I/libpersona: KNOX_SDCARD checking    this for 10243
01-11 09:52:41.686 28555-28555/? I/libpersona: KNOX_SDCARD not a persona
01-11 09:52:41.716 28555-28555/? I/SELinux: Function: selinux_compare_spd_ram , priority [2] , priority version is VE=SEPF_SM-G900F_5.0-1_0032
01-11 09:52:41.716 28555-28555/? E/SELinux: [DEBUG] get_category: variable seinfo: default sensitivity: NULL, cateogry: NULL
01-11 09:52:41.716 28555-28555/? I/art: Late-enabling -Xcheck:jni
01-11 09:52:41.756 28555-28555/? D/TimaKeyStoreProvider: TimaSignature is unavailable
01-11 09:52:41.756 28555-28555/? D/ActivityThread: Added TimaKeyStore provider
01-11 09:52:41.806 28555-28555/net.tchouny.httppost D/ResourcesManager: creating new AssetManager and set to /data/app/net.tchouny.httppost-1/base.apk
01-11 09:52:41.836 28555-28555/net.tchouny.httppost I/InstantRun: Instant Run Runtime started. Android package is net.tchouny.httppost, real application class is null.
01-11 09:52:41.856 28555-28555/net.tchouny.httppost W/art: Failed to find OatDexFile for DexFile /data/data/net.tchouny.httppost/files/instant-run/dex/slice-slice_4-classes.dex ( canonical path /data/data/net.tchouny.httppost/files/instant-run/dex/slice-slice_4-classes.dex) with checksum 0x9d676064 in OatFile /data/data/net.tchouny.httppost/cache/slice-slice_4-classes.dex
01-11 09:52:42.366 28555-28555/net.tchouny.httppost W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
01-11 09:52:42.636 28555-28555/net.tchouny.httppost D/Activity: performCreate Call secproduct feature valuefalse
01-11 09:52:42.636 28555-28555/net.tchouny.httppost D/Activity: performCreate Call debug elastic valuetrue
01-11 09:52:42.666 28555-28643/net.tchouny.httppost D/OpenGLRenderer: Render dirty regions requested: true
01-11 09:52:42.736 28555-28643/net.tchouny.httppost I/Adreno-EGL: <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build:  ()
                                                              OpenGL ES Shader Compiler Version: E031.25.01.03
                                                              Build Date: 03/03/15 Tue
                                                              Local Branch: LA.BF.1.1_RB1_20150108_025_1077123_1158499
                                                              Remote Branch: 
                                                              Local Patches: 
                                                              Reconstruct Branch: 
01-11 09:52:42.736 28555-28643/net.tchouny.httppost I/OpenGLRenderer: Initialized EGL, version 1.4
01-11 09:52:42.756 28555-28643/net.tchouny.httppost I/OpenGLRenderer: HWUI protection enabled for context ,  &this =0xa1622088 ,&mEglDisplay = 1 , &mEglConfig = 8 
01-11 09:52:42.756 28555-28643/net.tchouny.httppost D/OpenGLRenderer: Enabling debug mode 0
01-11 09:52:42.886 28555-28555/net.tchouny.httppost I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@1969d169 time:253291220
01-11 09:52:46.256 28555-28555/net.tchouny.httppost D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN
01-11 09:52:46.436 28555-28771/net.tchouny.httppost I/System.out: (HTTPLog)-Static: SBServiceAPI: getService class android.os.ServiceManager
01-11 09:52:46.436 28555-28771/net.tchouny.httppost I/System.out: (HTTPLog)-Static: isShipBuild true
01-11 09:52:46.436 28555-28771/net.tchouny.httppost I/System.out: (HTTPLog)-Thread-87638-928574752: SmartBonding Enabling is true, SHIP_BUILD is true, log to file is false, DBG is false

现在我的终端使用以下命令:

tchouny@tchounyX220:~$ curl -s -d '{"remote":"w"}' -v http://192.168.0.3/cgi-bin/toServerValue.cgi   
*   Trying 192.168.0.3...
* Connected to 192.168.0.3 (192.168.0.3) port 80 (#0)
> POST /cgi-bin/toServerValue.cgi HTTP/1.1
> Host: 192.168.0.3
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 14
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 14 out of 14 bytes
< HTTP/1.1 200 OK
< Date: Wed, 11 Jan 2017 08:34:35 GMT
< Server: Apache
< Debug: haha
< X-Orion-Version: 1.0
< Transfer-Encoding: chunked
< Content-Type: text/html;charset=iso-8859-1;debug:[{"remote":"w"}]
< 
{ "success": 1 }
* Connection #0 to host 192.168.0.3 left intact

2 个答案:

答案 0 :(得分:0)

目前,您正尝试在主线程which is blocked by Android上运行网络操作。因此,如果您想与WDTV进行通信,则需要在后台线程中进行。

将一个示例应用程序组合在一起以便在我自己的WDTV上进行测试后,我可以说这种方法确实有效。主要区别在于我设置了从EditText读取的URL,而不是硬编码。

/**
 * ButterKnife notation - don't copy verbatim,
 * copy what's inside the method and put into your button's onClickListener()
 */     
@OnClick(R.id.btn_send) public void send() {
    new Thread(new Runnable() {
        public void run() {
            sendCommand(txtCommand.getText().toString());
        }
    }).start();
}


/**
 * Don't run this method on the UI thread!
 */
private void sendCommand(String command) {
    InputStream in = null;
    OutputStream out = null;
    String reply = "";

    try {
        // Replace this with your hard-coded URL
        String url = String.format("http://%s/cgi-bin/toServerValue.cgi", txtIp.getText().toString());
        URL object=new URL(url);

        HttpURLConnection con = (HttpURLConnection) object.openConnection();
        con.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
        con.setRequestMethod("POST");
        con.setDoOutput(true);
        con.setDoInput(true);

        JSONObject json = new JSONObject();
        json.put("remote", command);

        out = con.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        writer.write(json.toString());
        writer.flush();
        writer.close();
        out.close();

        // If we're interested in the reply...
        int respCode = con.getResponseCode();
        if (respCode == HttpURLConnection.HTTP_OK) {
            String line;
            in = con.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            while ((line = reader.readLine()) != null) {
                reply += line;
            }

            reader.close();
            in.close();

            // Display the returned JSON in a text box, just for confirmation.
            // Code not necessary for this example
            showResult(reply);
        } else {
            showResult("Failed to connect: " + respCode);
        }

        con.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

请注意发送请求的方法如何包含在new Thread(...).start();语句中。这告诉Android在新的后台线程中运行您的代码。但请注意,这不是一种非常有效的做事方式。有更好的方法可以创建您将及时学习的背景线程,例如使用AsyncTaskExecutorService,但只有在您准备好时才会深入了解它们。

以及显示该应用的屏幕截图: WDTV test app - successful command sent

进一步阅读 - Processes and Threads

答案 1 :(得分:0)

这是最终答案。 第一个迈克尔为你的帮助。

我做了不同的测试,最后如果我使用JSON或基本字符串,它没有任何区别。 显而易见的是我们从http Connection获得响应的事实。

我测试了这个:

btStart.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            sendCommand("{\"remote\":\"w\"}");
        }
    });

}


private void sendCommand(final String command) {
        new Thread(new Runnable() {
            public void run() {

                InputStream in = null;
                OutputStream out = null;
                String reply = "";

                try {
                    String url = "http://192.168.0.3/cgi-bin/toServerValue.cgi";
                    URL object=new URL(url);

                    HttpURLConnection con = (HttpURLConnection) object.openConnection();
                    con.setRequestProperty("Content-Type", "text/html;charset=UTF-8");
                    con.setRequestMethod("POST");
                    con.setDoOutput(true);
                    //con.setDoInput(true);

                    //JSONObject json = new JSONObject();
                    //json.put("remote", command);
                    String httpPost = command;

                    out = con.getOutputStream();
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
                    writer.write(command.toString());
                    writer.flush();
                    writer.close();
                    out.close();

                    // If we're interested in the reply...
                    int respCode = con.getResponseCode();
                    /*if (respCode == HttpURLConnection.HTTP_OK) {
                        String line;
                        in = con.getInputStream();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                        while ((line = reader.readLine()) != null) {
                            reply += line;
                        }

                        reader.close();
                        in.close();

                        // Display the returned JSON in a text box, just for confirmation.
                        // Code not necessary for this example
                        tv.setText(reply);
                    } else {
                        tv.setText("Failed to connect: " + respCode);
                    }
*/
                    con.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }).start();
    }

并且它完美地工作只是因为我有这个:int respCode = con.getResponseCode(); 如果我删除响应它不起作用。 现在,如果我使用JSON格式代替基本字符串实际上更容易查询,结果是相同的。使用getResponse它可以工作,没有它。

Interresting。 劳伦