2016-09-21 98 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