2016-04-11 62 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()函數中創建單獨的線程並放置操作。