0

我正在尝试通过按下 android 上的按钮向互联网发送命令。

我知道网络部分不应该写在主线程上,所以我使用 AsyncTask 来做。

出乎意料的是,当我运行 Android Emulator 时,它总是在我按下按钮时关闭。

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)
4

3 回答 3

0

您可能应该在其内部设置按钮的单击侦听器onCreate()。现在您将它设置在 AsyncTask 的doInBackground().

所以,只需删除该行并将其添加到里面onCreate()

btnForward=(Button)findViewById(R.id.forwardBtn);     
btnForward.setOnClickListener(btnForwardListener);
于 2013-01-03T04:53:37.483 回答
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);
}
于 2013-01-03T04:54:16.020 回答
0

@BomberMan 的答案是正确的——你应该调用setOnClickListenerActivity 的onCreate但是你还需要做一些其他的事情

单击按钮时会出现错误,因为 onClick将(始终)在主线程中执行,因此您无法send_at_cmd从那里调用。您应该创建另一个 AsyncTask 子类来完成这项工作,并且execute它从onClick.

我猜你试图通过onClickListener在后台线程中分配来防止这种情况,认为它的onClick方法可能也会在后台运行。但事实并非如此。

于 2013-01-04T02:52:46.743 回答