Android: How do I obtain an app's total size dynamically?
===

In Android, I see many apps with loading screens. I know about the ProgressBar, implementing the AsyncTask method, but I have never seen anyone knowing how they managed to get the value for the total app size, or if they are loading assets, the total asset size.

By dynamically obtaining an app's total size, I will be able to add additional content to the app upon release, or after release. I could then be able to calculate the total progress the app had loaded.

So far, I made a workaround, shown below:

    package nttu.edu.activities;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.LinkedList;
    import java.util.Queue;
    
    import nttu.edu.R;
    import nttu.edu.graphics.Art;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.res.AssetManager;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.widget.ProgressBar;
    
    public class NewLoadingActivity extends Activity {
    	public ProgressBar bar;
    	private AssetManager assetManager;
    	public Handler handler;
    	public ProgressTask task;
    	
    	private final String[] list = {
    	// Art.sprites
    	"art/sprites.png", ...... };
    	
    	private class ProgressTask extends AsyncTask<Void, Void, Void> {
    		public int totalByteSize;
    		public int currentByteSize;
    		public Queue<Bitmap> bitmapQueue;
    		public Queue<byte[]> byteQueue;
    		
    		public ProgressTask() {
    			totalByteSize = 0;
    			currentByteSize = 0;
    			bitmapQueue = new LinkedList<Bitmap>();
    			byteQueue = new LinkedList<byte[]>();
    		}
    		
    		public void onPostExecute(Void params) {
    			Art.sprites = bitmapQueue.remove();
    			finish();
    		}
    		
    		public void onPreExecute() {
    			try {
    				for (int i = 0; i < list.length; i++) {
    					byte[] bytes = readFromStream(list[i]);
    					totalByteSize += bytes.length;
    					byteQueue.add(bytes);
    				}
    				bar.setMax(totalByteSize);
    			}
    			catch (IOException e) {
    				throw new RuntimeException(e);
    			}
    		}
    		
    		public void onProgressUpdate(Void... params) {
    			bar.setProgress(currentByteSize);
    		}
    		
    		@Override
    		protected Void doInBackground(Void... params) {
    			while (currentByteSize < totalByteSize) {
    				try {
    					Thread.sleep(1000);
    					if (byteQueue.size() > 0) {
    						byte[] bytes = byteQueue.remove();
    						Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    						bitmapQueue.add(bitmap);
    						currentByteSize += bytes.length;
    						this.publishProgress();
    					}
    				}
    				catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    			return null;
    		}
    		
    		private byte[] readFromStream(String path) throws IOException {
    			ByteArrayOutputStream output = new ByteArrayOutputStream();
    			byte[] buffer = new byte[1024];
    			int length = 0;
    			InputStream input = assetManager.open(path);
    			while (input.available() > 0 && (length = input.read(buffer)) != -1)
    				output.write(buffer, 0, length);
    			return output.toByteArray();
    		}
    		
    	}
    	
    	public void onCreate(Bundle b) {
    		super.onCreate(b);
    		this.setContentView(R.layout.progressbar);
    		assetManager = this.getAssets();
    		handler = new Handler();
    		task = new ProgressTask();
    		bar = (ProgressBar) this.findViewById(R.id.loadingBar);
    		if (bar == null) throw new RuntimeException("Failed to load the progress bar.");
    		task.execute();
    	}
    	
    	public void finish() {
    		Intent intent = new Intent(this, MenuActivity.class);
    		intent.putExtra("Success Flag", Art.sprites != null);
    		this.setResult(RESULT_OK, intent);
    		super.finish();
    	}
    }

The only main problem to this activity, is that I have to first add new assets to the list here near the top. The list array size is 58.:

`private final String[] list = {"art/sprites.png", ......};`

Then find out the total asset size from that list I wanted to load assets with, then use the total asset size to mark the 100% on my ProgressBar, and continue to update the ProgressBar as needed.

It's a slow process, and I was told that this may or may not be ideal if a user is to load the app and notice a lag during initialization. As mentioned that the list array is 58, when my app is loaded, it needs to calculate all of the asset size first, before doing the actual initialization.

I would like to make things quicker, just by setting all variables up without using AsyncTask and ProgressBar, but I liked to have a intro loading screen, just like all other apps in Google Play.

Therefore, how do I obtain an app's total size?