Wie kann man einen InputStream über bluetooth und in einem Textview?
Dies ist meine erste Frage in SO. Ich bin neu (und aufgeregt) in Android-Programmierung und hier ist mein PROBLEM: ich Baue ein Projekt mit meinem android-Handy und einem mikrocontroller. Der mikrocontroller hat einen Distanz-sensor und überträgt seinen Wert. Ich habe es geschafft, verbunden mit dem mikrocontroller und senden die richtigen Signale, aber ich kann nicht den Abstand mesurment, oder irgendetwas anderes. Die Anwendung stürzt nicht ab oder alles, was es einfach nicht die Daten vom mikrocontroller (mein Rechner bekommt die Daten von microcontroler (Daten string)). Meinen code aus der android app ist dies:
public class Beschleunigungsmesser erstreckt Aktivität {
//Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
private static final int RECIEVE_MESSAGE = 3;
//Program variables
private byte microcOut;
private boolean ledStat;
private boolean connectStat = false;
private Button btnled;
private Button connect_button;
private TextView yAccel, xAccel, incoming;
protected static final int MOVE_TIME = 80;
private long lastWrite = 0;
OnClickListener myClickListener;
ProgressDialog myProgressDialog;
private Toast failToast;
private Handler mHandler,h;
private StringBuilder sb = new StringBuilder();
//Sensor object used to handle accelerometer
private SensorManager mySensorManager;
private List<Sensor> sensors;
private Sensor accSensor;
//Bluetooth Stuff
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private ConnectThread mConnectThread = null;
private ConnectedThread mConnectedThread;
private String deviceAddress = null;
//Well known SPP UUID (will *probably* map to RFCOMM channel 1 (default) if not in use);
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
//Sound Clip to make app prettier
MediaPlayer myclip;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_accelerometer);
myclip = MediaPlayer.create(this, R.raw.cartcar);
myclip.start();
//Finds buttons in .xml layout file
btnled = (Button) findViewById(R.id.led_button1);
connect_button = (Button) findViewById(R.id.connect_button1);
yAccel = (TextView) findViewById(R.id.accText1);
xAccel = (TextView) findViewById(R.id.accText2);
incoming = (TextView) findViewById(R.id.incoming);
//Set Sensor
mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
sensors = mySensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if(sensors.size() > 0) accSensor = sensors.get(0);
myProgressDialog = new ProgressDialog(this);
failToast = Toast.makeText(this, R.string.failedToConnect, Toast.LENGTH_SHORT);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}
//Check if bluetooth connection was made to selected device
if (msg.what == 1) {
//Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);
//Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else {
//Connection failed
failToast.show();
}
}
};
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: //if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); //create string from bytes array
sb.append(strIncom); //append string
int endOfLineIndex = sb.indexOf("\r\n"); //determine the end-of-line
if (endOfLineIndex > 0) { //if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); //extract string
sb.delete(0, sb.length()); //and clear
incoming.setText("Data from Arduino: " + sbprint); //update TextView
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
//Check whether bluetooth adapter exists
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
Toast.makeText(this, R.string.no_bt_device, Toast.LENGTH_LONG).show();
finish();
return;
}
//If BT is not on, request that it be enabled.
if (!btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
/**********************************************************************
* Buttons for controlling BluCar
*/
connect_button.setOnClickListener(new View.OnClickListener() {
//Connect to Bluetooth Module
@Override
public void onClick(View v) {
if (connectStat) {
//Attempt to disconnect from the device
disconnect();
}else{
//Attempt to connect to the device
connect();
}
}
});
//Toggle Headlights
btnled.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ledStat) {
microcOut = (byte) (microcOut & 124);
btnled.setText(R.string.ledbuttonON);
ledStat = false;
}else{
microcOut = (byte) (microcOut | 128);
btnled.setText(R.string.ledbuttonOFF);
ledStat = true;
}
write(microcOut);
}
});
}
/** Thread used to connect to a specified Bluetooth Device */
public class ConnectThread extends Thread {
private String address;
private boolean connectionStatus;
ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}
public void run() {
//When this returns, it will 'know' about the server,
//via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);
//We need two things before we can successfully connect
//(authentication issues aside): a MAC address, which we
//already have, and an RFCOMM channel.
//Because RFCOMM channels (aka ports) are limited in
//number, Android doesn't allow you to use them directly;
//instead you request a RFCOMM mapping based on a service
//ID. In our case, we will use the well-known SPP Service
//ID. This ID is in UUID (GUID to you Microsofties)
//format. Given the UUID, Android will handle the
//mapping for you. Generally, this will return RFCOMM 1,
//but not always; it depends what other BlueTooth services
//are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}
//Discovery may be going on, e.g., if you're running a
//'scan for devices' search from your handset's Bluetooth
//settings, so we call cancelDiscovery(). It doesn't hurt
//to call it, but it might hurt not to... discovery is a
//heavyweight process; you don't want it in progress when
//a connection attempt is made.
btAdapter.cancelDiscovery();
//Blocking connect, for a simple client nothing else can
//happen until a successful connection is made, so we
//don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}
//Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}
//Send final result
if (connectionStatus) {
mHandler.sendEmptyMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
//When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
//Show please wait dialog
myProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.pleaseWait), getResources().getString(R.string.makingConnectionString), true);
//Get the device MAC address
deviceAddress = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
//Connect to device with specified MAC address
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();
}else {
//Failure retrieving MAC address
Toast.makeText(this, R.string.macFailed, Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_ENABLE_BT:
//When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
//Bluetooth is now enabled
} else {
//User did not enable Bluetooth or an error occured
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}
public void write(byte data) {
if (outStream != null) {
try {
outStream.write(data);
} catch (IOException e) {
}
}
}
public void emptyOutStream() {
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
}
}
}
public void connect() {
//Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceList.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
public void disconnect() {
if (outStream != null) {
try {
outStream.close();
connectStat = false;
connect_button.setText(R.string.disconnected);
} catch (IOException e) {
}
}
}
private final SensorEventListener mSensorListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public void onSensorChanged(SensorEvent event) {
//Checks whether to send steering command or not
long date = System.currentTimeMillis();
if (date - lastWrite > MOVE_TIME) {
yAccel.setText(" " + event.values[1]);
xAccel.setText(" " + event.values[0]);
if (event.values[1] > 2.5) {
//Turn right
microcOut = (byte) (microcOut & 248);
microcOut = (byte) (microcOut | 4);
}else if (event.values[1] < -2.5) {
//Turn left
microcOut = (byte) (microcOut & 244);
microcOut = (byte) (microcOut | 8);
}else {
//Center the steering servo
microcOut = (byte) (microcOut & 240);
}
write(microcOut);
lastWrite = date;
}
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_accelerometer, menu);
return true;
}
public void onResume() {
super.onResume();
mySensorManager.registerListener(mSensorListener, accSensor, SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onDestroy() {
emptyOutStream();
disconnect();
if (mSensorListener != null) {
mySensorManager.unregisterListener(mSensorListener);
}
super.onDestroy();
myclip.release();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket 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[256]; //buffer store for the stream
int bytes; //bytes returned from read()
//Keep listening to the InputStream until an exception occurs
while (true) {
try {
//Read from the InputStream
bytes = mmInStream.read(buffer); //Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); //Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
}
}
}
}
Ich habe alles gelesen über das Thema (BluetoothChat, Projekte von Menschen über das internet ...) und ich bin sehr müde. Jede Hilfe wird sehr geschätzt.
--EDIT--
Habe ich es geschafft, den inputstream in meine texteview. Mein problem ist jetzt, dass meine Anwendung, wenn es versucht, eine Verbindung zu meinem Gerät (mikrocontroller oder meinem pc) stecken in der progressdialog (es ist an das Gerät angeschlossen, aber der progressdialog wird nicht Weg)und wartet auf etwas zu kommen. Nach einer Weile (wie 5-6 Sek.), selbst wenn etwas kommt, bleibt stecken und ich muss ihn mit Gewalt zu schließen. Ich denke, das problem ist die Art der handler verarbeitet die thread. Im debugger ist es kein problem, alle Gewinde ok.
Die Veränderungen in meinem code sind:
In meinem ConnectThread:
` /* * - Thread verwendet, um eine Verbindung zu einem festgelegten Bluetooth-Gerät */
public class ConnectThread extends Thread {
private String Adresse;
private boolean connectionStatus;
ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}
public void run() {
//When this returns, it will 'know' about the server,
//via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);
//We need two things before we can successfully connect
//(authentication issues aside): a MAC address, which we
//already have, and an RFCOMM channel.
//Because RFCOMM channels (aka ports) are limited in
//number, Android doesn't allow you to use them directly;
//instead you request a RFCOMM mapping based on a service
//ID. In our case, we will use the well-known SPP Service
//ID. This ID is in UUID (GUID to you Microsofties)
//format. Given the UUID, Android will handle the
//mapping for you. Generally, this will return RFCOMM 1,
//but not always; it depends what other BlueTooth services
//are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}
//Discovery may be going on, e.g., if you're running a
//'scan for devices' search from your handset's Bluetooth
//settings, so we call cancelDiscovery(). It doesn't hurt
//to call it, but it might hurt not to... discovery is a
//heavyweight process; you don't want it in progress when
//a connection attempt is made.
btAdapter.cancelDiscovery();
//Blocking connect, for a simple client nothing else can
//happen until a successful connection is made, so we
//don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}
//Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}
try{
inStream = btSocket.getInputStream();
}catch (IOException e2){
connectionStatus = false;
}
int bytes; //bytes returned from read()
//Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
try {
byte[] b = new byte[64]; //buffer store for the stream
//Read from the InputStream
bytes = inStream.read(b); //Get number of bytes and message in "buffer"
mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, b).sendToTarget(); //Send to message queue Handler
} catch (IOException e) {
break;
}
}
//Send final result
if (connectionStatus) {
mHandler.obtainMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}
`
Und in meinem mHandler in meiner onCreate Methode:
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}
//Check if bluetooth connection was made to selected device
if (msg.what == 1) {
//Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);
//Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else if (msg.what == 2){
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); //create string from bytes array
sb.append(strIncom); //append string
int endOfLineIndex = sb.indexOf("."); //determine the end-of-line
if (endOfLineIndex > 0) { //if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); //extract string
sb.delete(0, sb.length()); //and clear
incoming.setText(sbprint); //update TextView
connectStat = true;
connect_button.setText(R.string.connected);
}else{
incoming.setText("Problem!");
}
}else {
//Connection failed
failToast.show();
}
}
};
Andere Sache, die ich brauche, ist, wie um den Puffer zu leeren, wenn es voll ist.
PS: vielen Dank an ALLE, die für seine/Ihre Hilfe bin ich wirklich dankbar.
Danke für Eure Antworten. Ich weiß, dass mein code so funktioniert wie es sollte (wenn es um das senden der microcOut byte). Zum senden des byte brauche ich nicht die Letzte Klasse ConnectedThread und das zweite hf. h. Diese wurden Ergänzungen zu meinem code von dem, was ich im Internet gefunden. Sie benötigen die DeviceList auch, um mir zu helfen? Nochmals vielen Dank.
Wieder, Sie wollen Schritt für Schritt durch den code mit einem debugger; vor allem die
run()
Methode in Ihrem ConnectedThread
. Prüfen Sie, ob bytes = mmInStream.read(buffer)
immer wieder sinnvoll ist (und ob es getroffen wird!). Es ist nicht unwahrscheinlich, dass eine Ausnahme geworfen wird, die man fangen und dann brechen aus der Schleife. Wenigstens drucken Sie die Ausnahmen, die Sie fangen, anstatt Sie zu ignorieren Sie, damit Sie wissen, was möglicherweise falsch läuft, wo. Sobald Sie über diese Informationen verfügen, können wir Ihnen besser helfen können.
InformationsquelleAutor user2149122 | 2013-03-14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Als alternative zur Verwendung der hf, nur die Informationen erhalten, die im Lauf der thread..
Habe ich es auf diese Art gemacht, und es funktioniert für mich.
Speichere ich alle Daten von der seriellen Verbindung, die in meiner Anwendung (Henry), dann ist jede Aktivität, die nutzen will, die info bekommt es von der Anwendung. Wenn Sie die Ansicht haben muss, um eine aktualisierte Sicht auf die Informationen, die ich fügen Sie einen timer, um die Ansicht zu kick einer refresh-Methode so oft wie ich möchte. Dies hat den zusätzlichen Vorteil des seins in der Lage, die Informationen zu verwenden, die von überall in Ihrem android-Anwendung.
Sende ich, über 10 Datenpunkte aus dem arduino, um das Gerät und über 3 Datenpunkte aus dem Gerät, um den arduino auf diese Weise. Ich habe meine eigene markup-Code rund um die Datenpunkte zu identifizieren.
Hoffe, das hilft!
InformationsquelleAutor Brian G