我试图为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://
时,这是logcatD/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
答案 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在新的后台线程中运行您的代码。但请注意,这不是一种非常有效的做事方式。有更好的方法可以创建您将及时学习的背景线程,例如使用AsyncTask和ExecutorService,但只有在您准备好时才会深入了解它们。
进一步阅读 - 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。 劳伦