Any example of using 2 different classes for onProgressUpdate in Asynctask? - java

I've been looking all over the place for this, and the only answer I've had was "use Pair", but I can't get this to work either.
Here's what I need to:
In Asynctask I need to update both a progress bar, and text. Because of this my Asynctask generic cannot be just Integer and not just String, but both. This is so I can have both classes within the "onProgressUpdate" method.
Can somebody give me some example or links as to how I add the strings and increase the integer in "doInBackground", and how to implement this in the "onProgressUpdate"?
Thank you very much!

Can you create your own simple class to hold the variables and then pass that?
Or, what if you pass a string that you can parse and get the values you need? If you take your first string += ":" + int, then make use of something like
String myString = passedString.substring(0, passedString.lastIndexOf(":")))
int i = Integer.parseInt(passedString.substring(passedString.lastIndexOf(":")+1));

As far as I understand your question; there are mainly two things which you want to do:
1) Handle a UI thread while in the doIneBackground().
2) Implement the onProgressUpdate().
Basically we shouldn't try to access the UI thread while a background process is running.
The reason for that is very clear... # OS level there will be so many thread will be running.And in that case It will be chaos on the screen, if we can update UI from background thread.
For the 2nd one I would like recommend you to take a look at this example:
ProgressDialog mProgressDialog;
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");
mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
In the AsynTask:
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
wl.acquire();
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_name.extension");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
return null;
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
}
catch (IOException ignored) { }
if (connection != null)
connection.disconnect();
}
} finally {
wl.release();
}
return null;
}}
The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
if (result != null)
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
}
Regards
Sathya

Related

Sending intents from a worker to an activity in a separate app

I have an app that writes to its local storage depending on user actions; said contents need to
be forwarded to another app.
My approach:
create a worker thread with a file observer pointed to local storage
start worker from the apps main activity
worker thread creates and sends intents with updated contents to separate app
I'm not sure (maybe need to open a separate question), but everything created in an activity gets destroyed when the activity is stopped, right? meaning that adding workers, file observers have the same life span as the activity they're defined in, right?
Code:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String FILE_OBSERVER_WORK_NAME = "file_observer_work";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "Creating file observer worker");
WorkManager workManager = WorkManager.getInstance(getApplication());
WorkContinuation continuation = workManager
.beginUniqueWork(FILE_OBSERVER_WORK_NAME,
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.from(APIWorker.class));
Log.i(TAG, "Starting worker");
continuation.enqueue();
final Button button = findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i(TAG, "Button clicked!");
String stuffToWriteToFile = getStuff();
String cwd = getApplicationInfo().dataDir;
String stuffFilePath= cwd + File.separator + "stuff.json";
PrintWriter stuffFile= null;
try {
stuffFile = new PrintWriter(stuffFilePath, "UTF-8");
stuffFile.println(stuffToWriteToFile);
stuffFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
}
#Override
public void onResume(){
super.onResume();
// start worker here?
}
#Override
public void onStart() {
super.onStart();
// start worker here?
}
}
APIWorker.java:
public class APIWorker extends Worker {
public APIWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
private static final String TAG = APIWorker.class.getSimpleName();
#NonNull
#Override
public Result doWork() {
Context applicationContext = getApplicationContext();
Log.d(TAG, "Observing stuff file");
FileObserver fileObserver = new FileObserver(cwd) {
#Override
public void onEvent(int event, #Nullable String path) {
if(event == FileObserver.CREATE ||
event == FileObserver.MODIFY) {
String cwd = applicationContext.getApplicationInfo().dataDir;
String stuffFilePath = cwd + File.separator + "stuff.json";
String fileContents;
File observedFile = new File(stuffFilePath);
long length = observedFile.length();
if (length < 1 || length > Integer.MAX_VALUE) {
fileContents = "";
Log.w(TAG, "Empty file: " + observedFile);
} else {
try (FileReader in = new FileReader(observedFile)) {
char[] content = new char[(int)length];
int numRead = in.read(content);
if (numRead != length) {
Log.e(TAG, "Incomplete read of " + observedFile +
". Read chars " + numRead + " of " + length);
}
fileContents = new String(content, 0, numRead);
Log.d(TAG, "Sending intent ");
String packageName = "com.cam.differentapp";
Intent sendIntent = applicationContext.getPackageManager().
getLaunchIntentForPackage(packageName);
if (sendIntent == null) {
// Bring user to the market or let them choose an app?
sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.setData(Uri.parse("market://details?id=" + packageName));
}
// sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, fileContents);
sendIntent.setType("application/json");
applicationContext.startActivity(sendIntent);
Log.d(TAG, "Intent sent ");
}
catch (Exception ex) {
Log.e(TAG, "Failed to read file " + path, ex);
fileContents = "";
}
}
}
}
};
fileObserver.startWatching();
return null;
}
}
Looking at the docs:
https://developer.android.com/guide/components/activities/background-starts
there are restrictions as to when activities can be started from the background but also exceptions, namely:
The app has a visible window, such as an activity in the foreground.
meaning (I think?) that as long as the user interacts with the app (MainActivity) the background worker should run, correct? It's stopped if the activity is paused/destroyed, right?
Usually you would use a Service if you have background processing to do that doesn't need user interaction (display or user input). If your app is in the foreground then your Service can launch other activities using startActivity().
Your architecture seems very strange to me. You are using a Worker, which has a maximum 10 minute lifetime. You are starting the Worker which then creates a FileObserver to detect creation/modification of files. It then reads the file and starts another Activity. This is a very complicated and roundabout way of doing things. I have doubts that you can get this working reliably.
Your Activity is writing the data to the file system. It could just call a method (on a background thread) after it has written the file that then forwards the data to another Activity. This would be much more straightforward and has a lot less moving parts.
I don't know exactly how the lifecycle of the Activity effects the Workers. I would assume that they are not directly linked to the Activity and therefore would not stop when the Activity is paused or destroyed.
I also notice that you are writing to a file on the main (UI) thread (in your OnClickListener). This is not OK and you should do file I/O in a background thread, because file I/O can block and you don't want to block the main (UI) thread.

Android app update dialog (without Google Play), Parse Error

I have coded an update dialog in my app which checks a json file on my server to see if an update is available and then shows an update app dialog box. I know that I can send users to playstore by using Intent but I saw facebook and some other apps also show the same dialog with update button and upon pressing that button, the app starts downloading and installing instantly without going to playstore. However when I added a download AsyncTask to download and install my app, it shows parse error.
Here is my code to download and parse:
public class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... urls) {
String path = "/sdcard/MyApp.apk";
try {
URL url = new URL(urls[0]);
URLConnection connection = url.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(path);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
return path;
}
// begin the installation by opening the resulting file
#Override
protected void onPostExecute(String path) {
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive" );
Log.d("Lofting", "About to install new .apk");
getContext().startActivity(i);
}
}
Can someone please tell me what am I doing wrong here?
Thanks in advance. :)

Assync Task freezing UI

I'm using an AsyncTask to download a file. But while it downloads the file, the UI gets freeze, and I have to wait the file to finish downloading to be able to do something. I've looked other threads, but I only found problems like running the task using .get().
Here's how I'm calling the AsyncTask
new DownloadFileFromUrl().execute("url");
and here's the AsyncTask
class DownloadFileFromURL extends AsyncTask<String, Integer, LineData> {
String fileDir = getApplicationContext().getFilesDir() + "/data.txt";
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected LineData doInBackground(String... f_url) {
int count;
//Download file--------------------------
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
InputStream input = new BufferedInputStream(url.openStream(),
8192);
OutputStream output = new FileOutputStream(fileDir);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) total * 100 / lenghtOfFile);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(LineData data) {
setDataFor24Hours();
setDataFor48Hours();
setDataFor72Hours();
showDataFor24Hours();
setList();
Log.e("Downloader: ", "done!");
}
}
I've made it to send Done! to the monitor when it finishes, and at this moment the UI gets unfreeze also, so the problem is in the AsyncTask.
I hope anyone can help me. Thanks in advance!
AsyncTask design in such a way that we can perform an action without freezing UI.
But doInBackgroundis only run in the background. But onPostExecute run on UI thread. So maybe your problem is in onPostExecute
Try to define like this.
new DownloadFileFromUrl().execute("url");

To many AsyncTask with upload at same time

please excuse my bad English I hope my explanations are understandable.
I am working on app, wich communicate with my server. It has different tasks. One of them is to upload my pictures from my smartphone to my server. I want, that my app do this in the background, with minimized use of memory and bandwidth.
Basically it works, but when I have to many new pictures, there are to many AsyncTask at the same time and reduce memory and bandwidth perceptible.
First I use a BroadcastReceiver, which start every 30 min my picture scanner.
The Scanner frist check, if the External Storage is readable, if is WIFI on and if there is a Internet Connection.
When that is true it query a list from pictures, which are already uploaded, from the database.
Then it request all pictures from the MediaStore library, check some minimum values (size, height, width) and if the pic isn't uploaded. When everything is ok, it start an AsyncTask for resize the image and upload it:
public class Scanner {
private Context context;
private PicDAO picDAO;
private Helper helper;
public Scanner(Context context) {
this.context = context;
picDAO = new PicDAO(context);
helper = new Helper(context);
}
public void startScan(){
if(helper.isExternalStorageReadable()
&& helper.isWifiOn()
&& helper.checkInternet()){
HashMap<Integer, String> pics = picDAO.picsHashMap();
Cursor mCursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Images.Media.DEFAULT_SORT_ORDER);
if(mCursor != null){
mCursor.moveToFirst();
while(!mCursor.isAfterLast()) {
PicClass pic = new PicClass(
mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media._ID)),
mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)),
mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA)),
mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.WIDTH)),
mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.HEIGHT)),
mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.SIZE)),
context
);
if(pic.getSize() > 25000
&& pic.getHeight() > 200
&& pic.getWidth() > 200
&& ( pics.get(pic.getIdent()) == null || !pics.get(pic.getIdent()).equals(pic.getDisplay_name()))
){
CreateThumb createThumb = new CreateThumb(context);
createThumb.execute(new PicClass[]{pic});
}
mCursor.moveToNext();
}
mCursor.close();
}
}
}
}
The creatThumb looks resize the Image and start a upload (using the volley library):
public class CreateThumb extends AsyncTask {
private Context context;
public CreateThumb(Context context) {
this.context = context;
}
#Override
protected PicClass doInBackground(PicClass... pics) {
Helper helper = new Helper(context);
String encodedString = "";
if(helper.isWifiOn() && helper.checkInternet()){
double dWidth = 1000;
double dHeight = 1000;
if(pics[0].getWidth() < (int) dWidth && pics[0].getHeight() < (int) dHeight){
dWidth = pics[0].getWidth();
dHeight = pics[0].getHeight();
}else{
if (pics[0].getWidth() > pics[0].getHeight()){
double div = pics[0].getWidth() / dWidth;
dHeight = pics[0].getHeight() / div;
}else{
double div = pics[0].getHeight() / dHeight;
dWidth = pics[0].getWidth() / div;
}
}
int width = (int) dWidth;
int height = (int) dHeight;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(pics[0].getPath(),bmOptions);
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap,width,height,0);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte[] byte_arr = stream.toByteArray();
encodedString = Base64.encodeToString(byte_arr, 0);
}
pics[0].setThumb_file(encodedString);
return pics[0];
}
#Override
protected void onPostExecute(final PicClass pic) {
if(!pic.getThumb_file().equals("")){
RequestQueue queue = Volley.newRequestQueue(context);
String url ="http://example.de/upload.php";
StringRequest postRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>(){
#Override
public void onResponse(String response) {
if(response.equals("OK")){
PicDAO picDAO = new PicDAO(context);
picDAO.savePic(pic);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {}
}
){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("img",pic.getThumb_file());
params.put("filename",pic.getDisplay_name() + ".jpg");
return params;
}
};
queue.add(postRequest);
}
}
}
The script on my server:
<?php
$base = $_POST['img'];
$filename = $_POST['filename'];
$binary = base64_decode($base);
$file = fopen('uploadedimages/'.$filename, 'wb');
fwrite($file, $binary);
fclose($file);
echo "OK";
The Problem is, when I have to many new pictures, it slow down the device and the internet connection, and I get this errors:
W/art: Suspending all threads took: 278.260ms
D/Volley: [2790] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://example.de/upload.php 0x8a9f5792 NORMAL 1> [lifetime=3447], [size=2], [rc=200], [retryCount=1]
How can I optimize my code or prevent that I have to many uploads simultaneously.
EDIT
I tried to rebuild the scanner part and use only one Queue where I add the request. But it seems like it doesn't work. When there is only one picture it works, but when the script add more than on request, it get no response an on the server is just the first picture.
public class Scanner {
private Context context;
private PicDAO picDAO;
private Helper helper;
public Scanner(Context context) {
this.context = context;
picDAO = new PicDAO(context);
helper = new Helper(context);
}
public void startScan(){
if(helper.isDeviceReady()){
Cursor mCursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Images.Media.DEFAULT_SORT_ORDER);
if(mCursor != null){
final RequestQueue mRequestQueue = Volley.newRequestQueue(context);
mCursor.moveToFirst();
while(!mCursor.isAfterLast()) {
final PicClass pic = new PicClass(mCursor, context);
if(pic.checkSize() && !picDAO.picExist(pic)){
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(pic.getPath(),bmOptions);
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap,pic.getNewSize()[0],pic.getNewSize()[1],0);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte[] byte_arr = stream.toByteArray();
pic.setThumb_file(Base64.encodeToString(byte_arr, 0));
StringRequest postRequest = new StringRequest(Request.Method.POST, "http://example.de/upload.php", new Response.Listener<String>(){
#Override
public void onResponse(String response) {
Log.d("DEBUG",response);
if(response.equals("OK")){
PicDAO picDAO = new PicDAO(context);
picDAO.savePic(pic);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
}
){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("img",pic.getThumb_file());
params.put("filename",pic.getDisplay_name() + ".jpg");
return params;
}
};
mRequestQueue.add(postRequest);
}
mCursor.moveToNext();
}
mCursor.close();
}
}
}
}
How can I optimize my code or prevent that I have to many uploads simultaneously
I'd drop AsyncTask in favor of using IntentService, which executes one job at the time and queues all the other. Of course the whole process is not as trivial as it may look so maybe using dedicated libraries like Android Priority Job Queue would be even better.
Well, to start don't make a new request queue for every upload. THe idea of a queue is that you add a bunch of requests to it, then run the queue and let Volley slowly go through the requests a small group of them at a time. You're creating dozens of queues, and I don't even see a call to run the queue.
I'd also be using a Thread rather than an AsyncTask. AsyncTasks should be one offs. In fact by using this many tasks you're starving out all the other things that may need a task, since they share a common Thread.

android Java - Textview not appending text when activity restarts

I've been trying to create a function in my app that consist in a bluetooth RFID scanner, it's paired to my device and I have it working and all.
I can receive the text and log it in the console, when I compile the activity, everything goes fine, the stick reads the code, and then appends the text into an EditText, but if I go back and enter the activity again, I can see the code in the log, but the text doesn't go to the Edittext.
I tried a lot of different approaches, but nothing seems to work :/
here's the code I have:
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bluetooth);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> bondedSet = mBluetoothAdapter.getBondedDevices();
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available.", Toast.LENGTH_LONG).show();
}
if (!mBluetoothAdapter.isEnabled()) {
Toast.makeText(this, "Please enable your BT and re-run this program.", Toast.LENGTH_LONG).show();
finish();
}
if (mBluetoothAdapter.isEnabled()) {
if(bondedSet.size() == 1){
for(BluetoothDevice device : bondedSet){
address = device.getAddress();
Log.d("bt:", address);
}
}
}
String address = "00:A0:96:2A:0A:1B";
out = (EditText) findViewById(R.id.output);
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
Log.d(TAG, device.getName() + " connected");
myConnection = new ConnectThread(device);
myConnection.start();
}
private class ConnectThread extends Thread {
private final BluetoothSocket mySocket;
Message msg;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.d(TAG, "CONNECTION IN THREAD DIDNT WORK");
}
mySocket = tmp;
}
Handler uiThreadHandler = new Handler() {
public void handleMessage(Message msg) {
out = (EditText) findViewById(R.id.output);
Object o = msg.obj;
out.append(o.toString().trim());
Log.d("handler", o.toString());
}
};
public void run() {
out = (EditText) findViewById(R.id.output);
Log.d(TAG, "STARTING TO CONNECT THE SOCKET");
setName("My Connection Thread");
InputStream inStream = null;
boolean run = false;
mBluetoothAdapter.cancelDiscovery();
try {
mySocket.connect();
run = true;
} catch (IOException e) {
Log.d(TAG, this.getName() + ": CONN DIDNT WORK, Try closing socket");
try {
mySocket.close();
Log.d(TAG, this.getName() + ": CLOSED SOCKET");
} catch (IOException e1) {
Log.d(TAG, this.getName() + ": COULD CLOSE SOCKET", e1);
this.destroy();
}
run = false;
}
synchronized (BluetoothActivity.this) {
myConnection = null;
}
byte[] buffer = new byte[1024];
int bytes;
// handle Connection
try {
inStream = mySocket.getInputStream();
while (run) {
try {
bytes = inStream.read(buffer);
readMessage = new String(buffer, 0, bytes);
msg = uiThreadHandler.obtainMessage();
msg.obj = readMessage;
uiThreadHandler.sendMessage(msg);
Log.d(TAG, "Received: " + readMessage);
} catch (IOException e3) {
Log.d(TAG, "disconnected");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
My guess is that this has something to do with the Thread itself. When you start your Activity for the first time, you also call .start() on the Thread, that would work fine.
The problem is when you leave your Activity and open it up again. In that case, one of onStop() or onPause() is called (depending on situation), and onRestart() or onResume() will be called afterwards respectively.
The trick comes now: Meanwhile all that process, your Thread is still running. As you show your code, it has not been stopped/paused, and keeps running all the time. So basically my tip is that there's something you do within your onCreate() method of your Activity that should also be done in your onPause() and onStop() events, and my another tip it's somewhere within your ConnectThread(BluetoothDevice device) method.
To know how to procceed, I'd firstly define both onStop() and onPause() methods within your Activity and see which is fired, log every attribute to see its value/state, and that way you'll be able to debug what is failing.
There's a diagram of the Activity lifecycle.
Problem was solved, the code works, and the TextView get the inputstream, the problem was when i left the activity, the thread continued to work, so far, no problem at all, after TONS of hours spent on this, i turn the TextView a static var and it worked :)
If anyone reads this, i hope it helps.

Categories