Avinash Gupta Avinash Gupta - 1 month ago 18
Java Question

Android runnable thread stuck somewhere

My Activity is using following onCreate() with a Runnable thread with while loop. Here is the code:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_user_registration);

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = sp.edit();

//Some Async task here

final File destFile = new File(filesDir, sp.getString(Constants.SharedPreferences.USER_ID,null)+ Constants.S3Bucket.IMAGE_EXTENSION);
final File downFile = new File(filesDir, Constants.S3Bucket.USER_DIRECTORY + sp.getString(Constants.SharedPreferences.USER_ID,null)+ Constants.S3Bucket.IMAGE_EXTENSION);
Runnable myRunnable = new Runnable() {


@Override
public void run() {

Log.v(LOG_TAG,"S3 file profile exists "+downFile.getAbsolutePath()+" "+downFile.exists());

while(!downFile.exists()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(LOG_TAG,"Error",e);

}
Log.v(LOG_TAG,"Inside while loop");
}

Log.v(LOG_TAG,"S3 file profile exists after while "+downFile.getAbsolutePath()+" "+downFile.exists());


Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();

}


The thread basically checks for the downFile which is being created by an AWS service. My activity keeps running and the control does not enter while loop. The condition is true for the first time and after that the control neither enters while loop nor exits. The statement before while loop is logged properly. So, basically MainActivity doesn't get started.

Is this a wrong implementation of threading? I don't understand what is happening here.

If I stop the app and run it again, the condition is now false and hence the control doesn't enter while loop but next Activity is loaded properly.

Answer

Use an AsyncTask for what you are doing and you don't have to be stuck in an endless while loop.

A full explanation of using them here: http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html

And I've implemented one for grabbinf images from a server here: (snippet below) http://wlgfx.com/programming/tcp-android-client-and-server-code/

Even Android has a tutorial on using them here: https://developer.android.com/reference/android/os/AsyncTask.html

example from last link:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
}

My own use of the AsynTask...

public class GetImageFromServer extends AsyncTask<Void, Void, Bitmap> {

    private final String tag = "WLGFX-AsyncBitmap";

    private Context context;
    private ImageView imageView;
    private int width;
    private int height;

    GetImageFromServer(Context ctx, ImageView view) {
        context = ctx;
        imageView = view;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        imageView.setImageBitmap(null);
        width = imageView.getWidth();
        height = imageView.getHeight();
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        imageView.setImageBitmap(bitmap);

        Log.d(tag, "Bitmap: " +
        "(" + bitmap.getWidth() +
        "," + bitmap.getHeight() + ")" +
        " " + bitmap.getByteCount());
    }

    @Override
    protected Bitmap doInBackground(Void... voids) {
        String head = "GSIF";
        byte[] header_data = head.getBytes();

        try {
            InetAddress address = InetAddress.getByName(Global.server_host);

            Socket socket = new Socket(address, Global.tcp_port);
            OutputStream out = socket.getOutputStream();
            out.write(header_data);

            byte[] dim = new byte[2];

            dim[0] = (byte)(width >> 8);
            dim[1] = (byte)width;
            out.write(dim);

            dim[0] = (byte)(height >> 8);
            dim[1] = (byte)(height);
            out.write(dim);

            byte[] length = new byte[4];
            readSocketBytes(socket, length);

            int size = (length[0] & 255) << 24 |
                    (length[1] & 255) << 16 |
                    (length[2] & 255)<< 8 |
                    length[3] & 255;

            byte[] image_data = new byte[size];
            readSocketBytes(socket, image_data);

            Bitmap bitmap = BitmapFactory.decodeByteArray(image_data, 0, size);

            socket.close();

            return bitmap;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    private void readSocketBytes(Socket socket, byte[] data) throws IOException {
        int length = data.length;
        InputStream in = socket.getInputStream();
        int position = 0;

        while (position < length) {
            int count = in.read(data, position, length - position);
            if (count > 0) position += count;
            else throw new IOException();
        }
    }
}