2016-09-21 101 views
-1

新的Android和開發一個應用程序,將提供藍牙數據到幾個不同的活動。我有一個ConnectActivity執行發現並將設備呈現給用戶,當用戶選擇設備時,如this討論中的人所建議的那樣,啓動BluetoothService。NPE()

BluetoothService延伸服務,並開始後臺線程最終將被用於對一個InputStream塊,和廣播數據到活動可用時(即,後經由startService這些活動輪詢())。

這是活動。定義接收器:

public class ConnectActivity extends AppCompatActivity { 
... 
    // My test receiver just to see if things are working. 
    private BroadcastReceiver mDataReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if(D) 
      Log.d(TAG, "Broadcast received."); 
    } 
}; 

啓動服務的onCreate():

protected void onCreate(Bundle savedInstanceState) { 
... 
    IntentFilter dataFilter = new IntentFilter(BluetoothService.INCOMING_DATA); 
    registerReceiver(mDataReceiver, dataFilter); 

    // Start the service with an intent identifying the context ("this" is an Activity, 
    // which inherits from Context) and the recipient. 
    Intent i = new Intent(this, BluetoothService.class); 
    i.putExtra(BluetoothService.COMMAND, "MY_COMMAND"); // Add the command as payload to the intent. 
    if(D) 
     Log.d(TAG, "Starting service."); 
    startService(i); 
} 

最後,連接上的按鈕按:

private void connect(){ 
    if(D) 
     Log.d(TAG, "Connecting to device " + (mBluetoothDevices.get(mSelectedPos).toString()) + " at position " + mSelectedPos); 

    final ProgressDialog dialog = new ProgressDialog(this); 
    dialog.setTitle("Connecting"); 
    dialog.setMessage("Please wait..."); 
    dialog.show(); 

    if(D) 
     Log.d(TAG, "Attempting to connect."); 
    mBluetoothService.connect(mBluetoothDevices.get(mSelectedPos), dialog); 

這裏是我的服務:

public class BluetoothService extends Service { 
... 
    public void connect (BluetoothDevice device, ProgressDialog dialog){ 
    .... 
    // Start the thread to connect to the device 
    mConnectThread = new ConnectThread(device, dialog, this); 
    mConnectThread.start(); 
} 

ConnectThread連接成功。sfully並開始其目的是將數據發送回acitvity,因爲它是在一個ConnectedThread我包括這一切,因爲這是我的問題是:

public class ConnectedThread extends Thread { 
    private BluetoothSocket mmSocket; 
    private final String mmMYNAME = "ConnectedThread"; 
    private final InputStream mmInStream; 
    private final OutputStream mmOutStream; 
    private final Context mmContext; 


    public ConnectedThread(BluetoothSocket socket, Context context) { 
     mmSocket = socket; 
     mmContext = context; 

     InputStream tryIn = null; 
     OutputStream tryOut = null; 

     // Get the BluetoothSocket input and output streams 
     try { 
      tryIn = mmSocket.getInputStream(); 
      tryOut = mmSocket.getOutputStream(); 
     } catch (IOException e) { 
      Log.e(TAG, mmMYNAME + " could not create streams.", e); 
     } 

     mmInStream = tryIn; 
     mmOutStream = tryOut; 
     mConnectedThreadEnabled = true; 
    } 

    @Override 
    public void run() 
    { 
     Thread.currentThread().setName(mmMYNAME); 
     Intent i = new Intent(INCOMING_DATA); 

     while(mConnectedThreadEnabled) { 
      SystemClock.sleep(1000); 
      if(D) 
       Log.d(TAG, "ConnectedThread is running."); 

      LocalBroadcastManager.getInstance(mmContext).sendBroadcast(i); //KABOOM 
     } 
     if(D) 
      Log.d(TAG, "Stopping ConnectedThread."); 

    } 

    public void cancel() { 
     if(D) 
      Log.d(TAG,"Canceling ConnectedThread."); 

     try { 
      if(D) 
       Log.d(TAG,"Shutting down existing socket."); 
      mConnectedThreadEnabled = false; 
      mmSocket.close(); 
     } catch (IOException e) { 
      Log.e(TAG, "close() of connect socket failed", e); 
     } 
    } 

} 

我的問題是,就行了:

LocalBroadcastManager.getInstance(mmContext).sendBroadcast(i); //KABOOM 

我收到:

顯示java.lang.NullPointerException:嘗試上的空對象引用 調用虛擬方法android.content.Context android.content.Context.getApplicationContext()'在android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:107) at android.support.v4.content.LocalBroadcastManager.getInstance(LocalBroadcastManager.java:102) at com.company.me.app.BluetoothService $ ConnectedThread.run (BluetoothService.java:255)

我不清楚問題是什麼,因爲調試表明mmContext和我都似乎正確創建。

+1

也許你的服務在你的線程運行時被破壞。 'ConnectedThread'持有'context.getApplicationContext()'而不是'context'。 – CommonsWare

+0

根據調試器,上下文不會顯示爲空。在緊急情況下,操作系統明確停止或回收之前,服務點是否還會繼續存在?順便說一下,我將鏈接到您的書,因爲我用它作爲服務的概述。 :)偉大的書。 – sje

+0

「在緊急情況下,操作系統明確停止或回收之後,服務點是否還會繼續存在?」 - startService()啓動的服務會一直運行,直到stopService()/ stopSelf(),或者服務崩潰或進程終止。但是,我不知道你的所有代碼,所以我不知道你有多久保持這項服務。感謝您的客氣話! – CommonsWare

回答

0

其執行mBluetoothService =新BluetoothService();

從來沒有自己創建組件的實例。擺脫這條線。已經使用mBluetoothService需要什麼被改寫爲:

  • 在服務本身,或

  • 使用服務綁定(例如,bindService(),與當時的活動,呼籲提供Binder方法),或

  • 使用一些其他的方式,避免了活性努力有直接的參考服務,更不用說創建服務本身

    的實例
+0

好的。我設計的服務僅支持默認的「輪詢藍牙設備」,通過命令模式和公共方法啓動初始連接。我應該通過命令模式(或綁定)支持_all_行爲,而不需要顯式實例化服務。非常感謝。 – sje