2016-04-11 58 views
0

我使用MainActivity进行蓝牙连接并通过它发送和接收消息,每个消息都有不同的线程。 现在我从这个活动启动一个片段,并在该片段我发送字符串主要活动通过使用MainActivity代码发送消息,但我的用户界面挂在这样做.. 任何人都可以帮助我解决这个问题。 这是我的MainActivity代码:通过蓝牙发送消息时UI挂起

public class MainActivity extends AppCompatActivity 
    implements NavigationDrawerFragment.NavigationDrawerCallbacks { 

/** 
* Fragment managing the behaviors, interactions and presentation of the navigation drawer. 
*/ 
private NavigationDrawerFragment mNavigationDrawerFragment; 

/** 
* Used to store the last screen title. For use in {@link #restoreActionBar()}. 
*/ 
private CharSequence mTitle; 

String address = null; 
BluetoothAdapter myBluetoothadpt = null; 
BluetoothSocket btSocket = null; 
private boolean isBtConnected = false; 
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 
BluetoothDevice device=null; 

static ConnectedThread manageConnectedSocket; 

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

    mNavigationDrawerFragment = (NavigationDrawerFragment) 
      getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); 
    mTitle = getTitle(); 

    // Set up the drawer. 
    mNavigationDrawerFragment.setUp(
      R.id.navigation_drawer, 
      (DrawerLayout) findViewById(R.id.drawer_layout)); 



// myBluetoothadpt = BluetoothAdapter.getDefaultAdapter(); 
    // device = myBluetoothadpt.getRemoteDevice("98:D3:31:20:7F:FB"); 

    // ConnectThread ct = new ConnectThread(device); 
    // ct.start(); 


} 

@Override 
protected void onResume() { 
    super.onResume(); 
    if (!myBluetoothadpt.isEnabled()) { 
     Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(enableIntent,1); 

    } 
} 
public static void sendMessage(String s){ 
    Log.d("track", "sendMessage "); 
    manageConnectedSocket.write(s.getBytes()); 

} 
@Override 
public void onNavigationDrawerItemSelected(int position) { 
    Fragment myFragment=null; 
    switch (position){ 
     case 0: 
     myFragment=new Home(); 
     break; 
     case 1: 
      myFragment=new Hall(); 
      break; 
     case 2: 
      myFragment=new Room1(); 
      break; 
     case 3: 
      myFragment=new Room2(); 
      break; 
     case 4: 
      myFragment=new Room3(); 
      break; 
     case 5: 
      myFragment=new Kitchen(); 
      break; 
     case 6: 
      myFragment=new Other(); 
      break; 
     case 7: 
      myFragment=new Help(); 
      break; 
     case 8: 
      myFragment=new ContactUs(); 
      break; 


    } 
    // update the main content by replacing fragments 
    FragmentManager fragmentManager = getSupportFragmentManager(); 
    fragmentManager.beginTransaction() 
      .replace(R.id.container, myFragment) 
      .commit(); 
} 

public void onSectionAttached(int number) { 
    switch (number) { 
     case 1: 
      mTitle = getString(R.string.title_section1); 

      break; 
     case 2: 
      mTitle = getString(R.string.title_section2); 
      break; 
     case 3: 
      mTitle = getString(R.string.title_section3); 
      break; 
    } 
} 

public void restoreActionBar() { 
    ActionBar actionBar = getSupportActionBar(); 
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 
    actionBar.setDisplayShowTitleEnabled(true); 
    actionBar.setTitle(mTitle); 
} 


@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    if (!mNavigationDrawerFragment.isDrawerOpen()) { 
     // Only show items in the action bar relevant to this screen 
     // if the drawer is not showing. Otherwise, let the drawer 
     // decide what to show in the action bar. 
     getMenuInflater().inflate(R.menu.main, menu); 
     restoreActionBar(); 
     return true; 
    } 
    return super.onCreateOptionsMenu(menu); 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 
    if (item.getItemId() == R.id.action_example) { 
     Intent serverIntent = new Intent(MainActivity.this, DeviceListActivity.class); 
     startActivityForResult(serverIntent, 1); 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 


public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (resultCode == Activity.RESULT_OK) { 
     String address = data.getExtras() 
       .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); 


     BluetoothDevice device = myBluetoothadpt.getRemoteDevice(address); 
     ConnectThread ct = new ConnectThread(device); 

    ct.start(); 

} 
} 

/** 
* A placeholder fragment containing a simple view. 
*/ 
public static class PlaceholderFragment extends Fragment { 
    /** 
    * The fragment argument representing the section number for this 
    * fragment. 
    */ 
    private static final String ARG_SECTION_NUMBER = "section_number"; 

    /** 
    * Returns a new instance of this fragment for the given section 
    * number. 
    */ 
    public static PlaceholderFragment newInstance(int sectionNumber) { 
     PlaceholderFragment fragment = new PlaceholderFragment(); 
     Bundle args = new Bundle(); 
     args.putInt(ARG_SECTION_NUMBER, sectionNumber); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    public PlaceholderFragment() { 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
     return rootView; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     ((MainActivity) activity).onSectionAttached(
       getArguments().getInt(ARG_SECTION_NUMBER)); 
    } 
} 
private class ConnectThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final BluetoothDevice mmDevice; 

    public ConnectThread(BluetoothDevice device) { 
     // Use a temporary object that is later assigned to mmSocket, 
     // because mmSocket is final 
     BluetoothSocket tmp = null; 
     mmDevice = device; 

     // Get a BluetoothSocket to connect with the given BluetoothDevice 
     try { 
      // MY_UUID is the app's UUID string, also used by the server code 
      tmp = device.createRfcommSocketToServiceRecord(myUUID); 
     } catch (IOException e) { } 
     mmSocket = tmp; 
     btSocket=mmSocket; 
    } 

    public void run() { 
     // Cancel discovery because it will slow down the connection 
     myBluetoothadpt.cancelDiscovery(); 

     try { 
      // Connect the device through the socket. This will block 
      // until it succeeds or throws an exception 
      mmSocket.connect(); 
     } catch (IOException connectException) { 
      // Unable to connect; close the socket and get out 
      try { 
       mmSocket.close(); 
      } catch (IOException closeException) { } 
      return; 
     } 

     // Do work to manage the connection (in a separate thread) 
     manageConnectedSocket=new ConnectedThread(btSocket); 
    } 

    /** Will cancel an in-progress connection, and close the socket */ 
    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { } 
    } 
} 

private class ConnectedThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final InputStream mmInStream; 
    private final OutputStream mmOutStream; 

    public ConnectedThread(BluetoothSocket socket) { 
     mmSocket = socket; 
     InputStream tmpIn = null; 
     OutputStream tmpOut = null; 

     // Get the input and output streams, using temp objects because 
     // member streams are final 
     try { 
      tmpIn = socket.getInputStream(); 
      tmpOut = socket.getOutputStream(); 
     } catch (IOException e) { } 

     mmInStream = tmpIn; 
     mmOutStream = tmpOut; 
    } 

    public void run() { 
     byte[] buffer = new byte[1024]; // buffer store for the stream 
     int bytes; // bytes returned from read() 

     // Keep listening to the InputStream until an exception occurs 
     while (true) { 

     } 
    } 

    /* Call this from the main activity to send data to the remote device */ 
    public void write(byte[] bytes) { 
     try { 
      Log.d("track", "in write" + bytes.toString()); 

      // mmOutStream.flush(); 
      mmOutStream.write(bytes); 
      // mmOutStream.flush(); 

     } catch (IOException e) { } 
    } 

    /* Call this from the main activity to shutdown the connection */ 
    public void cancel() { 
     try { 
      mmSocket.close(); 
     } catch (IOException e) { 
      Toast.makeText(MainActivity.this, "you are not connected!!", Toast.LENGTH_SHORT).show();} 
    } 
} 

} 

这里是我的片段:

public class Hall extends Fragment { 
ToggleButton t1h; 


    @Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 

     t1h.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 


      if (isChecked) { 

       String s = "t1o"; 
       Log.d("track", "onCheckedChanged " + isChecked); 
       MainActivity.sendMessage(s); // this is the method of MAINACTIVITY which then handles sending message over bluetooth 



      } else { 
       editor.putBoolean("t1hState", t1h.isChecked()); 
       String s = "t1f"; 
       Log.d("track", "onCheckedChanged " + isChecked); 


       MainActivity.sendMessage(s); 

      } 

     } 
    }); 
} 
} 

回答

0

,你应该避免非UI相关的东西在主线程上。当你这样做时,它会导致主线程挂起(并执行与非UI相关的工作)。

因此,您应该将这些工作委托给AsyncTask以帮助您完成工作并在完成时显示结果。

A的实现很好的例子,可以发现在: AsyncTask Android example

+0

我必须发送消息一个没有。有时候..所以我应该怎么调用execute()呢?我的意思是它会每次调用doinbackground().. –

+0

是的,你把逻辑处理你的消息在doInBackground()中发送并每次调用execute()您需要发送 – sihao

+0

一种优化的方式是将邮件整理并一次全部发送,如果交付时间不是问题 – sihao

0

,因为你是在当前或主线程发送消息,您的UI挂。如果您希望在后台发送数据而不影响当前线程,请使用AsyncTask并在AsyncTask的PostExcute()函数中创建单独的线程并放置操作。