java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序

时间:2013-04-04 00:03:01

标签: android multithreading service handler

我遇到了问题而且我不知道如何解决它。我想创建服务,将传感器更改发送到客户端(线程)。

我有线程在哪里开始服务,客户端线程接收答案并通过蓝牙发送。问题是我无法处理服务。

public class SensorMsgService extends Service implements SensorEventListener{

public static final int MSG_SAY_HELLO = 1;
public static final int MSG_REGISTER_CLIENT = 1;
public static final int MSG_UNREGISTER_CLIENT = 2;
public static final int MSG_SET_VALUE = 3;

static final String TAG = "Sensor Msg Service";

ArrayList<Messenger> mClients = new ArrayList<Messenger>();

private SensorManager mSensorManager;
private Sensor mSensor;

private ArrayList<Float> temp;

private Looper mServiceLooper;



public class IncomingHandler extends Handler{

    public IncomingHandler(Looper looper) {
          super(looper);
      }

    @Override
    public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_REGISTER_CLIENT:
                    mClients.add(msg.replyTo);
                    break;
            case MSG_UNREGISTER_CLIENT:
                    mClients.remove(msg.replyTo);
                    break;
            case MSG_SET_VALUE:
                    //mValue = msg.arg1;
                    for (int i = mClients.size() - 1; i >= 0; i--) {
                            try {
                                    /*mClients.get(i).send(
                                                    Message.obtain(null, MSG_SET_VALUE, 1, 0));*/
                                    Log.d(TAG, "Message from client");  
                            } 
                            //catch (RemoteException e) {
                            catch (Exception e) {
                                    // The client is dead. Remove it from the list;
                                    // we are going through the list from back to front
                                    // so this is safe to do inside the loop.
                                    mClients.remove(i);
                            }
                    }
                    break;
            default:
                    super.handleMessage(msg);
            }
    }

    //Toast.makeText(getApplicationContext(), "Hello service test", Toast.LENGTH_SHORT).show();
}

final Messenger mMessenger = new Messenger(new IncomingHandler(mServiceLooper));

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    Log.d(TAG, "binding");

    //return null;
    return mMessenger.getBinder();
}

@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
    // TODO Auto-generated method stub
    super.bindService(service, conn, flags);
 //     mServiceLooper.prepare();
    temp = new ArrayList<Float>();

    mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);

    return true;
}

@Override
public void unbindService(ServiceConnection conn) {
    // TODO Auto-generated method stub
    super.unbindService(conn);
    mSensorManager.unregisterListener(this);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub

}

@Override
public void onSensorChanged(SensorEvent event) {
    // TODO Auto-generated method stub

    temp.add(event.values[0]);
    temp.add(event.values[1]);
    temp.add(event.values[2]);

    for (int i = mClients.size() - 1; i >= 0; i--) {
        try {

                mClients.get(i).send(
                                Message.obtain(null, MSG_SET_VALUE, temp));
                Log.d(TAG, "Message service to client sending");    
        } 
        //catch (RemoteException e) {
        catch (Exception e) {
                // The client is dead. Remove it from the list;
                // we are going through the list from back to front
                // so this is safe to do inside the loop.
                mClients.remove(i);
        }
}

}

}

我发起了这项服务,正如我在帖子中所说:

    public class ConnectedThread extends Thread {

private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private Context mContext;

/** Messenger for communicating with service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mIsBound;
ArrayList<Float> temp;

private Looper mServiceLooper;


public ConnectedThread(BluetoothSocket socket, Context ctxx) {
    Log.d("ConnectedThread", "constructor ConnectedThread");
    mContext = ctxx;
    mmSocket = socket;
    InputStream tmpIn = null;
    OutputStream tmpOut = null;

    temp = new ArrayList<Float>();

    // Get the BluetoothSocket input and output streams
    try {
        tmpIn = socket.getInputStream();
        tmpOut = socket.getOutputStream();
    } catch (IOException e) {
        Log.e("ConnectedThread", "it was trying create input and output sockets", e);
    }

    mmInStream = tmpIn;
    mmOutStream = tmpOut;
}

public void run() {
    Log.i("ConnectedThread", "run mConnectedThread");
    byte[] buffer = new byte[1024];


    /*int i = 0;
    while(true)
    {
        Log.i("ConnectedThread", "sending int test value");
        write(i++);
    }*/

    doBindService();
}

/**
 * Write to the connected OutStream.
 * @param buffer  The bytes to write
 */
public void write(byte[] buffer) {
    try {
        mmOutStream.write(buffer);

    } catch (IOException e) {
        Log.e("ConnectedThread", "Exception during write", e);
    }
}

public void write(int out) {
    try {
        mmOutStream.write(out);

    } catch (IOException e) {
        Log.e("ConnectedThread", "Exception during write", e);
    }
}

public void cancel() {
    try {
        //mmOutStream.write(EXIT_CMD);
        mmSocket.close();
    } catch (IOException e) {
        Log.e("ConnectedThread", "close() of connect socket failed", e);
    }
}

///------------------------------

/**
 * Handler of incoming messages from service.
 */
class IncomingHandler extends Handler {



        @Override
        public void handleMessage(Message msg) {
                switch (msg.what) {
                case SensorMsgService.MSG_SET_VALUE:
                        temp = (ArrayList<Float>) msg.obj;
                        //mCallbackText.setText("Received from service: " + msg.arg1);
                        Log.d("Handle message from service", temp.get(0) + " " + temp.get(1) + " " + temp.get(2) + "\n");
                        break;
                default:
                        super.handleMessage(msg);
                }
        }
}

/**
 * Class for interacting with the main interface of the service.
 */
private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
                // This is called when the connection with the service has been
                // established, giving us the service object we can use to
                // interact with the service. We are communicating with our
                // service through an IDL interface, so get a client-side
                // representation of that from the raw service object.
                mService = new Messenger(service);
                //mCallbackText.setText("Attached.");


                // We want to monitor the service for as long as we are
                // connected to it.
                try {
                        Message msg = Message.obtain(null,
                                        SensorMsgService.MSG_REGISTER_CLIENT);
                        msg.replyTo = mMessenger;
                        mService.send(msg);


                        // Give it some value as an example.
                        msg = Message.obtain(null, SensorMsgService.MSG_SET_VALUE, this
                                        .hashCode(), 0);
                        mService.send(msg);
                } catch (RemoteException e) {
                        // In this case the service has crashed before we could even
                        // do anything with it; we can count on soon being
                        // disconnected (and then reconnected if it can be restarted)
                        // so there is no need to do anything here.
                }


                // As part of the sample, tell the user what happened.
                Toast.makeText(mContext, "Service connected",
                                Toast.LENGTH_SHORT).show();
        }


        public void onServiceDisconnected(ComponentName className) {
                // This is called when the connection with the service has been
                // unexpectedly disconnected -- that is, its process crashed.
                mService = null;
                //mCallbackText.setText("Disconnected.");


                // As part of the sample, tell the user what happened.
                Toast.makeText(mContext, "Service disconnedcted",
                                Toast.LENGTH_SHORT).show();
        }
};


/**
 * Target we publish for clients to send messages to IncomingHandler.
 */
final Messenger mMessenger = new Messenger(new IncomingHandler());



// do Bind

void doBindService() {
    // Establish a connection with the service. We use an explicit
    // class name because there is no reason to be able to let other
    // applications replace our component.

    mContext.bindService(new Intent(mContext, SensorMsgService.class),
                    mConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
    Log.d("ConnectedThread", "doBindService");
}

void doUnbindService() {
    if (mIsBound) {
            // If we have received the service, and hence registered with
            // it, then now is the time to unregister.
            if (mService != null) {
                    try {
                            Message msg = Message.obtain(null,
                                            SensorMsgService.MSG_UNREGISTER_CLIENT);
                            msg.replyTo = mMessenger;
                            mService.send(msg);
                    } catch (RemoteException e) {
                            // There is nothing special we need to do if the service
                            // has crashed.
                    }
            }


            // Detach our existing connection.
            mContext.unbindService(mConnection);
            mIsBound = false;
            //mCallbackText.setText("Unbinding.");
    }
}

}

问题是当我想运行这个帖子时:

  04-04 01:36:26.853: W/dalvikvm(29341): threadid=12: thread exiting with uncaught     exception (group=0x420372a0)
  04-04 01:36:26.853: E/AndroidRuntime(29341): FATAL EXCEPTION: Thread-11596
  04-04 01:36:26.853: E/AndroidRuntime(29341): java.lang.RuntimeException: Can't create    handler inside thread that has not called Looper.prepare()
  04-04 01:36:26.853: E/AndroidRuntime(29341):  at android.os.Handler.<init>   (Handler.java:121)
  04-04 01:36:26.853: E/AndroidRuntime(29341):  at com.nauka.bluetooth.ConnectedThread$IncomingHandler.<init>(ConnectedThread.java:127)
  04-04 01:36:26.853: E/AndroidRuntime(29341):  at com.nauka.bluetooth.ConnectedThread.<init>(ConnectedThread.java:200)

你能告诉我如何处理这个问题吗? THX

0 个答案:

没有答案