我试图通过按下android上的按钮向互联网发送命令。
我知道网络部分不应该写在主线程上,所以我使用AsyncTask来完成它。
出乎意料的是,当我运行Android模拟器时,它会在按下按钮时关闭。
public class DroneMain extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drone_main);
droneNavaSocket=new DroneNavaSocket();
droneNavaSocket.execute();
////////
btnForward=(Button)findViewById(R.id.forwardBtn);
}
public Button.OnClickListener btnForwardListener=
new Button.OnClickListener(){
@Override
public void onClick(View arg0) {
action = "Go Forward (pitch+)";
Log.e("///button","forward_enter1");
// at_cmd = "AT*PCMD=" + (seq++) + ",1," + intOfFloat(speed) + ",0,0,0";
at_cmd = "AT*PCMD=" + (seq++) + ",1,0," + intOfFloat(-speed) + ",0,0";
Log.e("///button","forward_enter2");
// AT*PCMD=1,0,-1110651699,0,0 'forward
Log.e("///button","outforward");
try {
send_at_cmd(at_cmd);
Log.e("///button","forward");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_drone_main, menu);
return true;
}
public void send_at_cmd(String at_cmd) throws Exception {
String ip = "192.168.1.1";
StringTokenizer st = new StringTokenizer(ip, ".");
byte[] ip_bytes = new byte[4];
if (st.countTokens() == 4){
for (int i = 0; i < 4; i++){
ip_bytes[i] = (byte)Integer.parseInt(st.nextToken());
}
}
else {
System.out.println("Incorrect IP address format: " + ip);
System.exit(-1);
}
try {
inet_addr = InetAddress.getByAddress(ip_bytes );
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("AT command: " + at_cmd);
byte[] buffer = (at_cmd + "\r").getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, inet_addr, PORT);
socket.send(packet);
Log.e("///send at command","at command topic");
//socket.receive(packet); //AR.Drone does not send back ack message (like "OK")
//System.out.println(new String(packet.getData(),0,packet.getLength()));
}
public class DroneNavaSocket extends AsyncTask<String, Integer, Boolean>{
protected void onPreExecute(){
// TODO Auto-generated method stub
//handler =new Handler();
//handler.postDelayed(runnable, 0);
super.onPreExecute();
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//Use UDP to transfer
try {
socket.setSoTimeout(3000);
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}/*Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. */
try {
send_at_cmd("AT*CONFIG=1,\"control:altitude_max\",\"2000\"");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //altitude max 2m
}
@Override
protected Boolean doInBackground(String... arg0)
{
btnForward.setOnClickListener(btnForwardListener);
btnBackward.setOnClickListener(BackwardListener);
btnLeft.setOnClickListener(btnLeftListener);
btnRight.setOnClickListener(btnRightListener);
btnUp.setOnClickListener(btnUpListener);
btnDown.setOnClickListener(btnDownListener);
// btnEmrgency.setOnClickListener(btnEmrgencyListener);
btnTakeoff.setOnClickListener(btnTakeoffListener);
btnLanding.setOnClickListener(btnLandingListener);
Log.e("///","end of on create");
return null;
}
}
}
01-04 10:35:56.522: I/dalvikvm(149): Jit: resizing JitTable from 4096 to 8192
01-04 10:35:58.291: W/InputMethodManagerService(149): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@41562da8 attribute=null
01-04 10:36:03.171: I/ActivityManager(149): START {act=android.intent.action.MAIN cat= [android.intent.category.LAUNCHER] flg=0x10104000 cmp=com.example.dronedivideandroid/.DroneMain u=0} from pid 218
01-04 10:36:03.271: D/dalvikvm(149): GC_FOR_ALLOC freed 508K, 6% free 11505K/12167K, paused 86ms, total 105ms
01-04 10:36:03.321: W/WindowManager(149): Failure taking screenshot for (246x410) to layer 21005
01-04 10:36:03.371: D/dalvikvm(647): Not late-enabling CheckJNI (already on)
01-04 10:36:03.382: I/Choreographer(218): Skipped 72 frames! The application may be doing too much work on its main thread.
01-04 10:36:03.391: D/dalvikvm(36): WAIT_FOR_CONCURRENT_GC blocked 0ms
01-04 10:36:03.411: I/ActivityManager(149): Start proc com.example.dronedivideandroid for activity com.example.dronedivideandroid/.DroneMain: pid=647 uid=10047 gids={3003, 1028}
01-04 10:36:03.522: D/dalvikvm(36): GC_EXPLICIT freed 38K, 4% free 7964K/8259K, paused 13ms+5ms, total 130ms
01-04 10:36:03.532: D/dalvikvm(36): WAIT_FOR_CONCURRENT_GC blocked 0ms
01-04 10:36:03.642: D/dalvikvm(36): GC_EXPLICIT freed <1K, 4% free 7964K/8259K, paused 4ms+14ms, total 115ms
01-04 10:36:03.652: D/dalvikvm(36): WAIT_FOR_CONCURRENT_GC blocked 0ms
01-04 10:36:03.761: D/dalvikvm(36): GC_EXPLICIT freed <1K, 4% free 7964K/8259K, paused 4ms+14ms, total 107ms
01-04 10:36:03.931: I/Choreographer(218): Skipped 124 frames! The application may be doing too much work on its main thread.
01-04 10:36:04.071: I/Choreographer(218): Skipped 37 frames! The application may be doing too much work on its main thread.
01-04 10:36:04.291: E/Trace(647): error opening trace file: No such file or directory (2)
01-04 10:36:04.391: I/ARMAssembler(35): generated scanline__00000077:03010104_00008001_00000000 [ 89 ipp] (110 ins) at [0x4124aa88:0x4124ac40] in 646000 ns
01-04 10:36:05.061: I/System.out(647): AT command: AT*CONFIG=1,"control:altitude_max","2000"
01-04 10:36:05.061: W/System.err(647): android.os.NetworkOnMainThreadException
01-04 10:36:05.071: W/System.err(647): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
01-04 10:36:05.071: W/System.err(647): at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:175)
01-04 10:36:05.071: W/System.err(647): at libcore.io.IoBridge.sendto(IoBridge.java:473)
01-04 10:36:05.071: W/System.err(647): at java.net.PlainDatagramSocketImpl.send(PlainDatagramSocketImpl.java:182)
01-04 10:36:05.081: W/System.err(647): at java.net.DatagramSocket.send(DatagramSocket.java:284)
01-04 10:36:05.081: W/System.err(647): at com.example.dronedivideandroid.DroneMain.send_at_cmd(DroneMain.java:268)
01-04 10:36:05.081: W/System.err(647): at com.example.dronedivideandroid.DroneMain$DroneNavaSocket.onPreExecute(DroneMain.java:311)
01-04 10:36:05.091: W/System.err(647): at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
01-04 10:36:05.091: W/System.err(647): at android.os.AsyncTask.execute(AsyncTask.java:534)
01-04 10:36:05.091: W/System.err(647): at com.example.dronedivideandroid.DroneMain.onCreate(DroneMain.java:40)
01-04 10:36:05.091: W/System.err(647): at android.app.Activity.performCreate(Activity.java:5008)
01-04 10:36:05.091: W/System.err(647): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
01-04 10:36:05.091: W/System.err(647): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
01-04 10:36:05.101: W/System.err(647): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
01-04 10:36:05.101: W/System.err(647): at android.app.ActivityThread.access$600(ActivityThread.java:130)
01-04 10:36:05.101: W/System.err(647): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
01-04 10:36:05.101: W/System.err(647): at android.os.Handler.dispatchMessage(Handler.java:99)
01-04 10:36:05.101: W/System.err(647): at android.os.Looper.loop(Looper.java:137)
01-04 10:36:05.101: W/System.err(647): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-04 10:36:05.101: W/System.err(647): at java.lang.reflect.Method.invokeNative(Native Method)
01-04 10:36:05.111: W/System.err(647): at java.lang.reflect.Method.invoke(Method.java:511)
01-04 10:36:05.111: W/System.err(647): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-04 10:36:05.111: W/System.err(647): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-04 10:36:05.111: W/System.err(647): at dalvik.system.NativeStart.main(Native Method)
01-04 10:36:05.131: E////(647): end of on create
01-04 10:36:05.311: D/gralloc_goldfish(647): Emulator without GPU emulation detected.
01-04 10:36:05.412: I/ActivityManager(149): Displayed com.example.dronedivideandroid/.DroneMain: +2s58ms
01-04 10:36:08.321: E////button(647): forward_enter1
01-04 10:36:08.321: D/AndroidRuntime(647): Shutting down VM
01-04 10:36:08.321: W/dalvikvm(647): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
01-04 10:36:08.352: E/AndroidRuntime(647): FATAL EXCEPTION: main
01-04 10:36:08.352: E/AndroidRuntime(647): java.lang.NullPointerException
01-04 10:36:08.352: E/AndroidRuntime(647): at com.example.dronedivideandroid.DroneMain.intOfFloat(DroneMain.java:64)
01-04 10:36:08.352: E/AndroidRuntime(647): at com.example.dronedivideandroid.DroneMain$1.onClick(DroneMain.java:75)
01-04 10:36:08.352: E/AndroidRuntime(647): at android.view.View.performClick(View.java:4084)
答案 0 :(得分:0)
您应该在onCreate()
内部设置按钮的单击侦听器。现在,您将其设置在AsyncTask的doInBackground()
。
因此,只需删除该行并将其添加到onCreate()
btnForward=(Button)findViewById(R.id.forwardBtn);
btnForward.setOnClickListener(btnForwardListener);
答案 1 :(得分:0)
下面
@Override
protected Boolean doInBackground(String... arg0) {
btnForward.setOnClickListener(btnForwardListener); //<<<<<here
//......your code...
您正在尝试从AsyncTask的doInBackground访问Ui元素。无法直接从doInBackground访问或更新Ui元素。
如果你想在doInBackground执行开始之前执行某些任务,那么将你的代码放在onPreExecute()
中如果您想在doInBackground完成后访问UI元素,请将当前的Ui元素移动到onPostExecute
为setOnClickListener
内的按钮设置onPreExecute()
,而不是doInBackground
@Override
protected void onPreExecute() {
super.onPreExecute();
btnForward.setOnClickListener(btnForwardListener);
}
答案 2 :(得分:0)
@ BomberMan的回答是正确的 - 你应该在活动的setOnClickListener
,中致电onCreate
,但还有其他事情要做} STRONG>。
单击按钮时出现错误,因为 onClick
将(始终)在主线程中执行,因此您无法调用send_at_cmd
从那里。您应该创建另一个AsyncTask子类来完成这项工作,并execute
从onClick
创建它。
我猜你试图通过在后台线程中分配onClickListener
来防止这种情况,也许可以考虑它的onClick
方法也可能在后台运行。但事实并非如此。