I have a goal to control some arduino device via BT with help of my android phone.
When I touch a screen and move my finger around, android app generate some data, depending on my finger position, forming a string message, and then trying to send it over BT.
The problem is, when the app attempts to send many many iterations of this command.
For example, the command is: String command = "[code]command(data)/";
When I just tap a time on a screen, the app write the command once and send it over BT, and it looks good on the other side (arduino).
But when I hold and move the finger, app trying to rewrite the command every "frame", and also trying to send this command every "frame" (I mean, every moment, many many times). And then I see something like: "[code]co[cod[co[c[mma(da]coode[c[co".
The feeling is... it gets one characters array and mixed it with another, when sending... or begin sending another message before stops sending previous.
Here is the code that gets some values on touch event:
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initPosX = x;
break;
case MotionEvent.ACTION_MOVE:
// some code that make counts and convert values...
// prepare string as a command.
String command = "[code]command(" + value + ")/";
Log.d("command", command);
// send data via BT
sendData(command);
break;
case MotionEvent.ACTION_UP:
//code
break;
default:
break;
}
Also I have BT settings up code, it all works good.
And this is the main part. Code that sending the string:
protected void sendData(String message) {
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
//some exception code
}
}
outStream = btSocket.getOutputStream();
So... I really don't know why this happens. I wasted entire day trying to search something about.
Will be very appreciated if someone can give me a glue, where to dig next.
Thanks.
UPDATE:
Arduino side code:
if (Serial.available() > 0) {
char c = Serial.read(); // read char from BT
serialMessage.concat(c); // add this char to string.
delay(5);
if (c == '/') {
lcd.setCursor(0,0);
lcd.print(serialMessage); // print message on a display.
command = serialMessage;
serialMessage = "";
}
}
else {
if (serialMessage != "") {
lcd.setCursor(0,0);
lcd.print(serialMessage); // print message on a display.
serialMessage = "";
}
//command = serialMessage;
}
UPDATE 2:
This is a real Serial input, when I tap once
[code]command(0.0)/
and when I move finger left and right
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.23)/
[code]cm()dm()[c]a.[em1[(/
em1[em1[]a.cca.[e)[dm(/
dm(/
em1[em1[co0ood)dmd4ood8oon2ccn0cca0/
ccn.[]a-)dm(6oon.[]a1[]od0o0[c]a1[]a1[em-/
em-)dm()dm(0odcn.cca0a.[]a.[em0/
em0)dm()dm()dm(/
em1/
em1[]a1[]a.ccn0oon7ccn4c]a.ccn.[em-)dm()oodod0ccn.ccn.[]m-/
d0ooood0ccn.ccn.[]a1[]a-/
em-/
em(5ood7c]a0/
em-)ood0[em0)dm()dm(3od)dm(/
dm(/
em1[em1[]a.c]a)dodm()ood2ccn./
ed9[]a1[]a-/
em-/
em()dm()dmd0od0ooood0oon.codecn1[]a0/
[dm(5ccn.cd0ccn1ccn.[]d4ooood7ocn3
UPDATE 3:
Taps without delay:
[
code]c
ommand(0.0)/
[code]command(0.0)/
[
code]c
ommand(0.0)/
[code]command(0.0)/
[
code]c
ommand(0.0)/
[code]command(0.0)/
UPDATE 4:
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.0)/
[code]command(0.01)/
[code]command(0.07)/
[code]command(0.15)/
[code]command(0.23)/
[code]command(0.29)/
[code]command(0.33)/
[code]command(0.37)/
[code]command(0.41)/
[co(0.44)/
[code]commandmmand(0.51)/
[code]code]command(0.6)/
[cod0.63)/
[cod0.65)/
[code]command(0.66)67)/
[code]command(0.68)/
2)/
Yes. It was overflowed serial.
I solve this issue in two steps.
First, I decrease delay for char reading on the arduino side from 5 to 1.
Second, I send a message/command only 10 times per second.
There is a code that makes this:
public void send(String string) {
if ((System.currentTimeMillis() - lastTimeSend) > 100) {
byte[] bytes = string.getBytes();
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
lastTimeSend = System.currentTimeMillis();
}
}
Related
I want to send the log lines to email in every 10 minutes.
To do that, I have used a Timer and inside of timer I send the logs via email.
However I loose some log lines between 2 emails.
For example my first email contains no lines which is normal according to my algorithm.
My second email contains log lines between 15.37 and 15.38 seconds.
My third email contains logs in between 15.44 and 15.48 time intervals.
My fourth email contains logs in between 15.55 and 15.58 time intervals.
As you can see I loose some of my logs but I could not find a way to avoid that.
Following is my code in my service class:
#Override
public void onCreate() {
super.onCreate();
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
sendLogFile();
}
}, 0, 1000 * 60 * 10 );
}
Inside of sendSupport method the second parameter is sent as a content of the log lines where logs is a static string variable.
private void sendLogFile() {
mInteractor.sendSupport("LOG FILE", "MSG"+logs, "SUBJECT"+ System.currentTimeMillis(), "",
result -> {
Timber.log(Log.DEBUG, "sendSupport Thread.currentThread().getName() " + Thread.currentThread().getName());
if (result.isSuccess) {
Timber.d("is sent");
writeLogFile();
} else {
Timber.d("is NOT sent");
}
}
);
}
private void writeLogFile()
{
try {
StringBuilder logBuilder = new StringBuilder();
process = Runtime.getRuntime().exec( "logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
logBuilder.append(line + "\n");
}
logs = logBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
As a result I could not figure out how am I going to be able to get all logs in periodically in my email.
Thanks.
While the #Knossos answer is pointing the reason why some logs are missing, it doesn't suggest how to use that knowledge to reliably get the logs from users' phones, when you don't have an access to their devices to run some adb commands.
Here is what I suggest to do instead:
As you do already use Timber, just add some more power to it. Namely, add an additional LoggingTree that will save the logs into a file, instead of just posting them to Logcat. You can have many Timber Trees working simultaneously, so you can have both Logcat and File logs if needed.
Use the same timer to send an email message when and where needed. But, instead of using access to logcat -d, simply use the file where Timber have already written the logs. Don't forget to flush the stream before sending the email. In order not to send the same logs again and again, configure the FileTree in a way that it creates a new file every time when a previous one is sent (seta a new file name via a method call, for example).
Profit :)
To log into two different systems (Trees), you need to simply add one more to Timber:
Timber.plant(new Timber.DebugTree());
Timber.plant(new FileLoggingTree());
And here is an example of FileLoggingTree(source):
public class FileLoggingTree extends Timber.DebugTree {
private static Logger mLogger = LoggerFactory.getLogger(FileLoggingTree.class);
private static final String LOG_PREFIX = "my-log";
public FileLoggingTree(Context context) {
final String logDirectory = context.getFilesDir() + "/logs";
configureLogger(logDirectory);
}
private void configureLogger(String logDirectory) {
// reset the default context (which may already have been initialized)
// since we want to reconfigure it
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.reset();
RollingFileAppender<ILoggingEvent> rollingFileAppender = new RollingFileAppender<>();
rollingFileAppender.setContext(loggerContext);
rollingFileAppender.setAppend(true);
rollingFileAppender.setFile(logDirectory + "/" + LOG_PREFIX + "-latest.html");
SizeAndTimeBasedFNATP<ILoggingEvent> fileNamingPolicy = new SizeAndTimeBasedFNATP<>();
fileNamingPolicy.setContext(loggerContext);
fileNamingPolicy.setMaxFileSize("1MB");
TimeBasedRollingPolicy<ILoggingEvent> rollingPolicy = new TimeBasedRollingPolicy<>();
rollingPolicy.setContext(loggerContext);
rollingPolicy.setFileNamePattern(logDirectory + "/" + LOG_PREFIX + ".%d{yyyy-MM-dd}.%i.html");
rollingPolicy.setMaxHistory(5);
rollingPolicy.setTimeBasedFileNamingAndTriggeringPolicy(fileNamingPolicy);
rollingPolicy.setParent(rollingFileAppender); // parent and context required!
rollingPolicy.start();
HTMLLayout htmlLayout = new HTMLLayout();
htmlLayout.setContext(loggerContext);
htmlLayout.setPattern("%d{HH:mm:ss.SSS}%level%thread%msg");
htmlLayout.start();
LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<>();
encoder.setContext(loggerContext);
encoder.setLayout(htmlLayout);
encoder.start();
// Alternative text encoder - very clean pattern, takes up less space
// PatternLayoutEncoder encoder = new PatternLayoutEncoder();
// encoder.setContext(loggerContext);
// encoder.setCharset(Charset.forName("UTF-8"));
// encoder.setPattern("%date %level [%thread] %msg%n");
// encoder.start();
rollingFileAppender.setRollingPolicy(rollingPolicy);
rollingFileAppender.setEncoder(encoder);
rollingFileAppender.start();
// add the newly created appenders to the root logger;
// qualify Logger to disambiguate from org.slf4j.Logger
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.DEBUG);
root.addAppender(rollingFileAppender);
// print any status messages (warnings, etc) encountered in logback config
StatusPrinter.print(loggerContext);
}
#Override
protected void log(int priority, String tag, String message, Throwable t) {
if (priority == Log.VERBOSE) {
return;
}
String logMessage = tag + ": " + message;
switch (priority) {
case Log.DEBUG:
mLogger.debug(logMessage);
break;
case Log.INFO:
mLogger.info(logMessage);
break;
case Log.WARN:
mLogger.warn(logMessage);
break;
case Log.ERROR:
mLogger.error(logMessage);
break;
}
}
}
The problem is that logcat -d is only delivering you the latest X bytes of data from the stream. You aren't guaranteed to get everything between 10 minute intervals.
In the best case, you get what you want. In the worst cases, you miss log data or log sections overlap (you get some from the previous dump too).
You can see this here: adb logcat -d | dd
...
03-27 11:36:27.474 791 22420 E ResolverController: No valid NAT64 prefix (147, <unspecified>/0)
03-27 11:36:27.612 3466 3521 I PlayCommon: [657] alsu.c(187): Successfully uploaded logs.
453+111 records in
499+1 records out
255863 bytes (256 kB, 250 KiB) copied, 0,136016 s, 1,9 MB/s
As you can see, it is clearly a 256 kB chunk that is pulled through logcat -d.
On the plus side, you can change that! If you look at adb logcat --help you can see options.
For example, if you use adb logcat -d -t '100000' | dd (all logs in the last 100000 seconds. I now have the following:
...
03-27 11:45:41.687 791 1106 I netd : bandwidthSetGlobalAlert(2097152) <0.90ms>
03-27 11:45:42.098 21897 23376 V FA : Inactivity, disconnecting from the service
2237+1558 records in
2879+1 records out
1474408 bytes (1,5 MB, 1,4 MiB) copied, 1,20785 s, 1,2 MB/s
1.5 MB of logs. You should be able to get all logs with this.
You log the timestamp of each logcat pull, then use that each time to determine the seconds since the last pull.
I hope that helps!
You cannot send an email from the device without user interaction or implementing the email function yourself that allows to do this without user interaction.
Most apps have some api endpoint to send the logs to.
I have little knowledge of Java and Android. What I am trying to do is to open /dev/ttyS0 in an Android App which should talk to the serial line, but I am getting lost.
My device is rooted, and from a command line I can "echo ...>/dev/ttyS0" and also read from it, but I get lost trying to do that in Java. For start, I can not find a method to open a file in simple read-write mode, without coping with buffers and other intricacies (clearly, I want unbuffered I/O).
I searched the Internet, but all examples refer to USB which is not available for me. Then I've found the UartDevice class, but it is a class to derive a proper implementation from...
I tried to use the File class, and attach to it both a Reader and a Writer class, but the compiler complains and, frankly, I am not sure it is the way to go. I would need a skeleton code to start from; I miss a simple TextFile class with unbuffered read() and write() methods to be used at the same time on the same open file!
Can someone point me in the right direction thanks?
After many tries, and with the help of much information from the SO site, I finally succeded in the task. Here is the code:
public class MainActivity
extends AppCompatActivity {
File serport;
private FileInputStream mSerR;
private FileOutputStream mSerW;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// let this program to access the serial port, and
// turn off the local echo. sudo() is a routine found here on S.O.
sudo("chmod a+rw /dev/ttyS0");
sudo("stty -echo </dev/ttyS0");
// open the file for read and write
serport = new File("/dev/ttyS0");
try {
mSerR = new FileInputStream(serport);
mSerW = new FileOutputStream(serport);
} catch (FileNotFoundException e) {}
// edLine is a textbox where to write a string and send to the port
final EditText edLine = (EditText) findViewById(R.id.edLine);
// edTerm is a multiline text box to show the dialog
final TextView edTerm = findViewById(R.id.edTerm);
// pressing Enter, the content of edLine is echoed and sent to the port
edLine.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
// Perform action on key press
String cmd = edLine.getText()+"\n";
edTerm.append(cmd);
byte[] obuf = cmd.getBytes();
try {
mSerW.write(obuf);
} catch (IOException e) {}
edLine.setText("");
// read the reply; some time must be granted to the server
// for replying
cmd = "";
int b=-1, tries=8;
while (tries>0) {
try {
b = mSerR.read();
} catch (IOException e) {}
if (b==-1) {
try {
Thread.sleep(5);
} catch (InterruptedException e) {}
--tries;
} else {
tries=3; // allow more timeout (more brief)
if (b==10) break;
cmd = cmd + (char) b;
}
}
// append the received reply to the multiline control
edTerm.append(cmd+"\n");
return true;
}
return false;
}
});
}
}
Please note the presence of the sudo() command in the code: it is there to give r/w permissions to the ttyS0 file, and to disable its echo option. If those permissions+options are already right, or another mean to set them exists, then the sudo() command is not needed.
Note: I believe that the sudo() command implies that the device must be rooted.
All File access in Java is done via input and output streams. If you want to open a file, you simply create a FileOutputStream or FileInputStream for it. These are unbuffered streams. If you then want to write raw bytes you can wrap that in a ByteArrayOutputStream or ByteArrayInputStream.
To do character mode, you can use a Writer. An OutputStreamWriter with a charset of ascii can wrap the FileOutputStream. That should do the character conversion for you. Just don't use a FileWriter- while it seems like the right fit, it has no option to select a character set, and the default is not ascii. For reading in, use an InputStreamReader.
i've been trying to make an app for mobile (both iOS and Android) and what this app does is quite simple:
Download a txt file from webserver
"Run" txt, the txt file has a command like "display" or "play" with an URL to resource (jpg or mp4)
Download or stream the resource to a texture in the scene (done)
Using GoogleVR (LatestVersion) to shot the whole thing
Now the problem is that as i start the coroutine to download stuff the game freezes on mobile but it doesn't freeze while in Editor.
Here's the code:
IEnumerator retrieveCommand(){
print ("Retrieving command...");
WWW rx = new WWW (host + "command.txt"); // host is the URL of server
yield return rx; // wait for end WWW
if (!string.IsNullOrEmpty (rx.error)) { // if there's an error i stop execution of coroutine
print (rx.error);
mex.text = rx.error;
yield break;
}
print ("Command: " + rx.text);
if (lastCommand != rx.text.Trim ()) { // if last command retrieved is NOT the same as the current
lastCommand = rx.text.Trim ();
command = rx.text.Trim ();
string[] argv = command.Split ('|'); // command is in form of <cmd>|parameter
mexdisplay = argv [0]; // argv[0] contains command, argv[1] contains the paramter
switch (argv [0]) { // what's the command?
case "PLAY":
video.GetComponent<MediaPlayerCtrl> ().Play ();
break;
case "STOP":
video.GetComponent<MediaPlayerCtrl> ().Stop ();
break;
case "PAUSE":
video.GetComponent<MediaPlayerCtrl> ().Pause ();
break;
case "GRAB": // set video resource
try {
video.GetComponent<MediaPlayerCtrl> ().m_strFileName = host + argv [1];
} catch (Exception e) {
print ("Exception: " + e);
}
break;
case "DISPLAY": // downloads and shows picture
print ("Display: " + host + argv [1]);
rx = new WWW (host + argv [1]);
yield return rx;
if (!string.IsNullOrEmpty (rx.error)) {
print (rx.error);
mex.text = rx.error;
yield break;
}
video.GetComponent<Renderer> ().material.mainTexture = rx.texture;
break;
}
}
asdf = true;
}
The coroutine is called every 10s by Update:
void Update(){
if(asdf){ // bool, if false -> running coroutine, if true -> not running->count 10 seconds
curr += Time.deltaTime;
if (curr >= time) { // time=10f, if counted to 10s start coroutine and reset timer
asdf = false;
curr = 0;
StartCoroutine (retrieveCommand ());
}
}
}
edit:
So it turns out it's like the camera stops rendering... any help? i'm using the GoogleVR camera prefabs...
I've been asking questions regarding my Android project that continually plots Bluetooth data in real-time.
Basically what I've already done is create a first version of my app by cobbling together some open source code Blueterm and OrientationSensorExample
It's been suggested that I add a thread, a handler, a Service, or use Async Task, or AIDL, etc. But I don't know how to use any of these and would appreciate an explanation.
Here's a description of the Blueterm open source code I started with (see link above). Blueterm is basically a terminal emulator program that communicates over Bluetooth. It consists of several activities with Blueterm being the most important. It discovers, pairs, and connects with a remote Bluetooth device that supports SPP/RfComm. When connected I can use Blueterm to configure the remote device by sending it commands to turn on sampling, change the number of channels to sample (to one channel), change to format of the incoming data (I like comma separated data), etc
Here's a description of the OrientationSensorExample open source code I started with (see link above). It's basically an example application of the AnroidPlot library. The OrientationSensor activity implements SensorEventListener. This includes overriding onSenorChanged() which is called whenever new orientation sensor data is taken, and it redraws the graph.
Having cobbled together these two open source projects (Blueterm and OrientationSensorExample) into one application (Blueterm) here's a description of how the overall application (Blueterm) works. When I start Blueterm the whole screen emulates a nice blue terminal. From the Options Menu I discover, pair with, connect to, and configure a remote bluetooth device as described above. Once I have configured the remote device, I go again to the Options Menu and select "Plot data" which launches the Plot activity. The terminal emulator goes away, and a nice scrolling real-time plot from the Plot activity shows up.
As far as I can tell there is a background thread that calls an update() method as follows:
/**
* Look for new input from the ptty, send it to the terminal emulator.
*/
private void update() {
int bytesAvailable = mByteQueue.getBytesAvailable();
int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length);
try {
int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead);
append(mReceiveBuffer, 0, bytesRead);
//VTR use existing handler that calls update() to get data into plotting activity
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
In the update() method I found it convenient to call my Plot.plotData() method and pass it the same date that is passed to the append() method to plot the data. NOTE: This only works if plotData() is a static method. No one has been able to explain why.
Anyway plotData() is a static method and here's how it and it's helper methods look now:
private static StringBuffer strData = new StringBuffer("");
public static void plotData(byte[] buffer, int base, int length) {
Log.i("Entering: ", "plotData()");
/*
byte[] buffer = (byte[]) msg.obj;
int base = msg.arg1;
int length = msg.arg2;
*/
for (int i = 0; i < length; i++) {
byte b = buffer[base + i];
try {
if (true) {
char printableB = (char) b;
if (b < 32 || b > 126) {
printableB = ' ';
}
Log.w("Log_plotData", "'" + Character.toString(printableB)
+ "' (" + Integer.toString(b) + ")");
strData.append(Character.toString(printableB));
if (b == 10)
{
Log.i("End of line: ", "processBlueData()");
Log.i("strData", strData.toString());
splitData(strData);
strData = new StringBuffer("");
}
}
} catch (Exception e) {
Log.e("Log_plotData_exception", "Exception while processing character "
+ Integer.toString(i) + " code "
+ Integer.toString(b), e);
}
}
Log.i("Leaving: ", "plotData()");
}
private static void splitData(StringBuffer strBuf) {
String strDash = strBuf.toString().trim();
String[] strDashSplit = strDash.split("-");
for (int ndx = 0; ndx < strDashSplit.length; ndx++)
{
if (strDashSplit[ndx].length() > 0)
Log.i("strDashSplit", ndx + ":" + strDashSplit[ndx]);
String strComma = strDashSplit[ndx].trim();
String[] strCommaSplit = strComma.split(",");
for (int mdx = 0; mdx < strCommaSplit.length; mdx++)
{
if (strCommaSplit[mdx].length() > 0)
Log.i("strCommaSplit", mdx + ":" + strCommaSplit[mdx]);
if (mdx == 1)
{
int raw = Integer.parseInt(strCommaSplit[1],16);
Log.i("raw", Integer.toString(raw));
float rawFloat = raw;
Log.i("rawFloat", Float.toString(rawFloat));
float ratio = (float) (rawFloat/65535.0);
Log.i("ratio", Float.toString(ratio));
float voltage = (float) (5.0*ratio);
Log.i("voltage", Float.toString(voltage));
nowPlotData(voltage);
}
}
}
}
public static void nowPlotData(float data) {
// get rid the oldest sample in history:
if (plotHistory.size() > HISTORY_SIZE) {
plotHistory.removeFirst();
}
// add the latest history sample:
plotHistory.addLast(data);
// update the plot with the updated history Lists:
plotHistorySeries.setModel(plotHistory, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
//VTR null pointer exception?
if (plotHistoryPlot == null)
Log.i("aprHistoryPlot", "null pointer exception");
// redraw the Plots:
plotHistoryPlot.redraw();
}
If it is strongly recommended that plotData() not be a static method and that I should do something else please explain here and how. Thanks!
This might be a question much better suited for Code Review, rather than here. Perhaps you can reformulate to post it there, or trim it a lot to repost it here.
Furthermore, to answer: "It's been suggested that I add a thread, a handler, a Service, or use Async Task, or AIDL, etc. But I don't know how to use any of these and would appreciate an explanation.", the best advise would be to link you to a book about android, such as: http://commonsware.com/Android/ . Chapters 35 and 36 deal with services, while chapter 20 is about threads. You will never get an answer as complete as those chapters here.
I've got a weird problem. When I debug my program and put a breakpoint before the "writeBlock" command to write my MifareClassic card, everything is going fine. The card is written and my program continues.
If I remove the breakpoint, I get an "IO Exception : transceived failed"! I put the breakpoint back without changing my code, it works again!
I'm lost... Could it be possible that the problem comes from the speed of the program execution? Having a breakpoint makes the execution slower...
Here's my code (the authentication is done before this function):
private static boolean WriteMfcBlock(MifareClassic mfc, int blockNumber, byte[] value) {
try {
byte[] toWrite = new byte[MifareClassic.BLOCK_SIZE];
//if the value is less than 16 bytes, fill it with '0'
for (int i=0; i<MifareClassic.BLOCK_SIZE; i++) {
if (i < value.length) toWrite[i] = value[i];
else toWrite[i] = 0;
}
if (!mfc.isConnected()) mfc.connect();
mfc.writeBlock(blockNumber, toWrite);
//Check if the writing is well done
byte[] read = mfc.readBlock(blockNumber);
for (int i = 0; i < MifareClassic.BLOCK_SIZE; i++ ) {
if (toWrite[i] != read[i]) return false;
}
return true;
}
catch (IOException e) {
textViewInfo.setText("IO EXCEPTION");
return false;
}
}
Thanks for your help
Sylvain
I go a step forward. It seems that it can come from a thread issue.
The "writeblock" command of the MifareClassic has to be triggered by the main process of the activity.
In my app, it's a button (implementing OnClickListener) that triggered the "writeblock".
When in debugging mode, the debug thread can hide this behavior because it's the main thread and make the app running well.
So from now, what I did is just to ask the user to remove the tag from the rf field and put it back. So I get the intent that a tag has been discovered again and then I can do the "writeblock" command without any problem.
Finally I thing the best way to handle read and write on tags is the create 2 activities, one for readings and one for writings.
If you have any comment or other way to do it .. please, answer this thread.
Sylvain