Donc, j'écris une application qui lit des lectures dans les données du port série. Ces données proviennent d'un arduino qui est connecté à un capteur de force - essentiellement, l'application est destinée à mesurer le poids de quelque chose. J'ai trouvé le code du port série ici: https://www.allaboutcircuits.com/projects/communicate-with-your-arduino-through-android/, et je l'utilise dans plusieurs activités différentes (puisque j'ai besoin d'une activité pour l'étalonnage, une activité pour la mesure réelle, etc.). Mon problème est que le même code de port série fonctionne dans une activité et ne fonctionne pas dans une autre. Il travaille dans cette activité, par exemple:Le même code fonctionne différemment dans différentes activités android
public class EnterDataActivity extends AppCompatActivity {
private static final long TIMER_DELAY = 5000;
private static final long TIMER_LENGTH = 15000;
EditText enterMax, enterMin;
Button submitMax, submitMin, continueButton;
Chronometer emptyBagTimer;
boolean firstMeasure, getEmptyBagData, canEnterMax, canEnterMin;
ArrayList<String> emptyBagData;
float maxLoad, minLoad;
// serial port variables:
public final String ACTION_USB_PERMISSION = "com.example.jake.USB_PERMISSION";
UsbManager usbManager;
UsbDevice device;
UsbSerialDevice serialPort;
UsbDeviceConnection connection;
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
@Override
public void onReceivedData(byte[] arg0) {
String data;
try {
data = new String(arg0, "UTF-8");
if(getEmptyBagData)
emptyBagData.add(data);
} catch (UnsupportedEncodingException e) {}
}
};
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
serialPort.setBaudRate(9600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
start();
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
stop();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_data);
usbManager = (UsbManager) getSystemService(USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);
enterMax = (EditText) findViewById(R.id.enterMax);
enterMin = (EditText) findViewById(R.id.enterMin);
submitMax = (Button) findViewById(R.id.submitMax);
submitMin = (Button) findViewById(R.id.submitMin);
continueButton = (Button) findViewById(R.id.continueButton);
emptyBagTimer = (Chronometer) findViewById(R.id.emptyBagTimer);
firstMeasure = true;
getEmptyBagData = false;
canEnterMax = true;
canEnterMin = true;
emptyBagData = new ArrayList<>();
start();
}
// method: measureEmptyBag
// description: this method is called when the button to measure the mass of the empty bag is
// pressed. It starts the chronometer and serial port, first waiting TIMER_DELAY milliseconds
// from the button press, then sets a boolean to true that causes the serial data to be added to
// an arraylist over the next TIMER_LENGTH milliseconds. It then sets the next views in the
// enter data process to visible. The firstMeasure boolean is to prevent spamming.
public void measureEmptyBag(View view){
if(firstMeasure) {
firstMeasure = false;
start();
emptyBagTimer.setBase(SystemClock.elapsedRealtime());
emptyBagTimer.start();
emptyBagTimer.setFormat("Waiting - %s");
emptyBagTimer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() <= TIMER_DELAY)
emptyBagTimer.setFormat("Waiting - %s");
else if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() <= TIMER_DELAY + TIMER_LENGTH) {
emptyBagTimer.setFormat("Calculating - %s");
getEmptyBagData = true;
}
else if (SystemClock.elapsedRealtime() - emptyBagTimer.getBase() > TIMER_DELAY + TIMER_LENGTH) {
getEmptyBagData = false;
emptyBagTimer.stop();
enterMax.setVisibility(View.VISIBLE);
submitMax.setVisibility(View.VISIBLE);
}
else
emptyBagTimer.setFormat("Waiting - %s");
}
});
}
}
// method: setMaxLoad
// description: called when the submit button is pressed for the max load, this method trys to
// pull the max load value from it edit text and store it. If that is successful (the user has
// entered in a number) then it sets the next views in the enter data process to visible.
public void setMaxLoad(View view){
if(canEnterMax){
try {
canEnterMax = false;
maxLoad = Float.parseFloat(enterMax.getText().toString());
enterMin.setVisibility(View.VISIBLE);
submitMin.setVisibility(View.VISIBLE);
} catch (Exception e) {} // in case the user enters a non number
}
}
// method: setMinLoad
// description: called when the submit button is pressed for the min load, this method trys to
// pull the min load value from its edit text and store it. If that is successful (the user has
// entered in a number) then it sets the next view in the enter data process to visible.
public void setMinLoad(View view){
if(canEnterMin){
try {
canEnterMin = false;
minLoad = Float.parseFloat(enterMin.getText().toString());
continueButton.setVisibility(View.VISIBLE);
} catch (Exception e) {} // in case the user enters a non number
}
}
// method: continuePressed
// description: this method is called when the continue button is pressed. It averages all of the
// data read in over the measure empty mass period to find the mass when empty, then writes that
// value along with maxLoad and minLoad to a file for later use. Finally it starts the pump
// activity
public void continuePressed(View view){
int emptyMassSum = 0;
int emptyMass;
// cleaning up emptyBagData to only include 3,2, or 1 digit numbers (the serial output gets
// wonky sometimes and spits out weird numbers that would throw off the calculations below,
// so those numbers need to be removed)
for (int i = emptyBagData.size() - 1; i >= 0; i--)
if (emptyBagData.get(i).length() != 3)
emptyBagData.remove(i);
// add up all the values in emptyBagData (try catch in case a non-number was read in)
for (int i = emptyBagData.size() - 1; i >= 0; i--) {
try {
emptyMassSum += Integer.parseInt(emptyBagData.get(i));
} catch (Exception e) {
emptyBagData.remove(i);
}
}
emptyMass = emptyMassSum/emptyBagData.size();
FileOutputStream outputStream;
String dataOut = "E" + emptyMass + "Mx" + maxLoad + "Mn" + minLoad + ";";
try {
outputStream = openFileOutput("BagData.txt", Context.MODE_PRIVATE);
outputStream.write(dataOut.getBytes());
outputStream.close();
} catch (Exception e) {
continueButton.setText(R.string.file_write_error_message);
}
Intent intent = new Intent(this, PumpActivity.class);
startActivity(intent);
}
// serial port methods:
public void start() {
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 10755 || deviceVID == 9025)//Arduino Vendor ID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
public void stop() {
if(serialPort!=null)
serialPort.close();
}
}
Par « ça marche », je veux dire que je peux obtenir les données à venir à partir du port série et de l'utiliser. Cependant, le même code ne fonctionne pas ici:
public class PumpActivity extends AppCompatActivity {
File calibrationData, bagData;
int mass1, mass2, read1, read2, emptyMassNum;
float maxLoad, minLoad;
double slope, currentMassVal, emptyMass;
boolean status, runTimer;
TextView statusTextView, currentMassTextView;
Button stop;
Thread updateMass;
ArrayList<String> inData;
// this does two things when the handleMessage method is called:
// 1) it takes the most recent data read in and calculates the current mass from it, then updates
// the current mass text view to reflect that
// 2) it takes that newly calculated mass and sees if status should change, depending on how much
// mass there currently is. It also writes a value to the serial port (back to the arduino)
// depending on that status. It then updates the status text view to reflect this
Handler updateMassHandler = new Handler(){
public void handleMessage(Message msg){
// mass calculation
try{currentMassVal = calculateMass(Integer.parseInt(inData.get(inData.size()-1)));} catch (Exception e){} // try-catch in case data isn't an int
inData.clear();
currentMassTextView.setText(String.format(getResources().getString(R.string.current_mass_string), currentMassVal));
// status check with new mass
if (currentMassVal >= maxLoad)
status = true;
else if (currentMassVal <= minLoad)
status = false;
statusTextView.setText(String.format(getResources().getString(R.string.pump_status), getStatus()));
// writing back to arduino
if (serialPort != null) {
if (status)
serialPort.write("1".getBytes());
else
serialPort.write("0".getBytes());
}
}
};
// serial port variables:
public final String ACTION_USB_PERMISSION = "com.example.jake.USB_PERMISSION";
UsbManager usbManager;
UsbDevice device;
UsbSerialDevice serialPort;
UsbDeviceConnection connection;
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
@Override
public void onReceivedData(byte[] arg0) {
String data;
try {
data = new String(arg0, "UTF-8");
inData.add(data);
} catch (UnsupportedEncodingException e) {}
}
};
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
serialPort.setBaudRate(9600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
start();
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
stop();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pump);
usbManager = (UsbManager) getSystemService(USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);
status = false;
statusTextView = (TextView) findViewById(R.id.statusTextView);
statusTextView.setText(String.format(getResources().getString(R.string.pump_status), getStatus()));
currentMassTextView = (TextView) findViewById(R.id.currentMassTextView);
currentMassTextView.setText(R.string.calculating_text);
stop = (Button) findViewById(R.id.stopButton);
runTimer = true;
currentMassVal = 0;
inData = new ArrayList<>();
// thread that "calls" the handleMessage method in the upDateMassHandler every 100 milliseconds
updateMass = new Thread(new Runnable() {
@Override
public void run() {
while(runTimer){
updateMassHandler.sendEmptyMessage(0);
try{Thread.sleep(100);} catch (InterruptedException e){}
}
}
});
// thanks to stackOverflow for the file reading code
// reading and parsing from calibration data
calibrationData = new File(getFilesDir(), "CalibrationData.txt");
StringBuilder text = new StringBuilder();
// reading in the calibration data from the file (of the same name)
try {
BufferedReader br = new BufferedReader(new FileReader(calibrationData));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
} catch (IOException e) {}
// parsing values from calibration data
String calibData = text.toString();
calibData = calibData.substring(3);
mass1 = Integer.parseInt(calibData.substring(0, calibData.indexOf('R')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
read1 = Integer.parseInt(calibData.substring(0, calibData.indexOf('M')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
mass2 = Integer.parseInt(calibData.substring(0, calibData.indexOf('R')));
calibData = calibData.substring(calibData.indexOf(':') + 1);
read2 = Integer.parseInt(calibData.substring(0, calibData.indexOf('.')));
slope = ((double) (mass2 - mass1)/(read2 - read1)); // calculating slope of masses and reads to allow
// calculation of mass of an unknown read
// reading and parsing from bag data
bagData = new File(getFilesDir(), "BagData.txt");
StringBuilder text2 = new StringBuilder();
// reading in the bag data from the file (of the same name)
try {
BufferedReader br = new BufferedReader(new FileReader(bagData));
String line;
while ((line = br.readLine()) != null) {
text2.append(line);
text2.append('\n');
}
br.close();
} catch (IOException e) {}
// parsing values frm bag data
String bagData = text2.toString();
bagData = bagData.substring(1);
emptyMassNum = Integer.parseInt(bagData.substring(0, bagData.indexOf('M')));
bagData = bagData.substring(bagData.indexOf('x') + 1);
maxLoad = Float.parseFloat(bagData.substring(0, bagData.indexOf('M')));
bagData = bagData.substring(bagData.indexOf('n') + 1);
minLoad = Float.parseFloat(bagData.substring(0, bagData.indexOf(';')));
emptyMass = calculateMass(emptyMassNum); // emptyMassNum is the values read in from the arduino
// this converts it to a mass
updateMass.start();
start();
}
// method: calculateMass
// description: calculates the mass of the object on the transducer based off of the value read
// in and the data gotten from calibration
// input: int readVal - the value read in
// output: double - the calculated mass
public double calculateMass(int readVal){
return (slope * (readVal-read1)) + mass1;
}
// method: getStatus
// description: returns a string representation of the status
public String getStatus(){
if(status)
return "running";
else
return "stopped";
}
// method: stop
// description: stops everything when the stop button is pressed
public void stop(View view){
status = false;
runTimer = false;
stop();
stop.setText(R.string.button_stopped);
}
// serial port methods:
public void start() {
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 10755 || deviceVID == 9025)//Arduino Vendor ID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
public void stop() {
if(serialPort!=null)
serialPort.close();
}
}
Pour une raison quelconque, la méthode onReceivedData dans la variable mCallback ne semble pas être appelé dans la deuxième activité (celui ne fonctionne pas). Je suis assez sûr que c'est le problème, je ne suis pas sûr pourquoi il est appelé dans une activité et pas dans une autre avec le même code. Si cette méthode n'est pas appelée, je ne peux pas accéder aux données qui arrivent, ce qui est mon problème.
Une aide précieuse serait grandement appréciée!
Mec c'est trop code pour une question. –