I recently made this application for root users who mod their device frequently.
Now I noticed quite strange behaviour with the application's install size.
When I used a regular activity with views being initialized from the XML file, the size was 715 kb
.
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) findViewById(R.id.display);
powermenu = (Button) findViewById(R.id.powermenu);
turnoffscreen = (Button) findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
}
After I switched to a dialog which was created setting a view which contained the widgets in the XML file. The app size was now 200kb
.
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
//setContentView(R.layout.main_layout);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.main_layout, null);
executeEvents = new ExecuteEvents(this);
display = (TextView) view.findViewById(R.id.display);
powermenu = (Button) view.findViewById(R.id.powermenu);
turnoffscreen = (Button) view.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) view.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
Dialog dialog = new Dialog(this);
dialog.setContentView(view);
dialog.setTitle(getResources().getString(R.string.app_name));
dialog.show();
}
It reduced to 80kb
when I used this:
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
dialog = new Dialog(this);
dialog.setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) dialog.findViewById(R.id.display);
powermenu = (Button) dialog.findViewById(R.id.powermenu);
turnoffscreen = (Button) dialog.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) dialog.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
dialog.setTitle(getString(R.string.app_name));
dialog.show();
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
dialog.dismiss();
MainActivity.this.finish();
}
});
}
I also noticed another strange change in application size when I tried to add an animation with the last style of code(the 80kb
one). The app size became a hefty 1 MB
. This is how I initialized the animation and tried calling it when the button was clicked :
private static final ScaleAnimation animation = new ScaleAnimation(1, .95f, 1, .95f, Animation.RELATIVE_TO_SELF, (float)0.5, Animation.RELATIVE_TO_SELF, (float)0.5);//declared as global variable
Inside the onCreate method:
animation.setDuration(1000);
animation.setFillAfter(false);
After which I called it in the onClickListener
:
mapButton.startAnimation(animation);
Why is there such a drastic change in application size when I haven't added any new resources but only changed the style of code? Where is there such a HUGE difference in the way I initialize widgets present in dialogs? Why is there a HUGE difference when I add an animation the way I've added it?
Follow up question:
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) this.findViewById(R.id.display);
powermenu = (Button) this.findViewById(R.id.powermenu);
turnoffscreen = (Button) this.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) this.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
}
SPECULATION
Could this be due to the packages or classes which are imported? It makes sense for the animation
bit of the question at least.
Would adding the context to which the views are initialized reduce memory usage?
Since apps are compressed when they're downloaded, it can make install sizes larger than download sizes. When an app has a larger install size, more space is required on a user's device to complete the installation. After the app is opened, its size on the disk varies depending on the app usage.
Typically, individual apps can use between 40MB – 1GB of phone storage.
No, update doesn't always have to guarantee an increase in size of an app. Generally, app developers add new libraries and codes in updates which tends to increase the size of the app. But if developer decides to remove certain codes and libraries, it surely will decrease the size of the app.
Yup, your speculations are close to be right, so as you may know all your Java code first is compiled to Java bytecode by say javac
, then dx
converts them to Dalvik bytecode, your dalvik bytecode file (a.k.a. dex
) is packaged inside your apk (btw apk size doesn't vary much as zip compression helps) usually as classes.dex
which later on when you install the apk in you device, Android might optimize it for that particular device (a.k.a. odex
).
So to verify that your final cached dex
actually changes and is the responsible for this size change, by say just adding animations, you can find it either by unzipping your apk or inside your device, I always find the second option more exciting:
So here is your dex
without animation (your 80kb
):
And your app info:
So here is your dex
with animation (your 1 MB
):
And your app info:
A closer look you can find they are truly different by just looking right in your dalvik bytecode constants pool:
For some reason I didn't get such radical size difference yet it is noticiable, I built your app using gradle + Android Studio so I think they help and optimize things a bit.
Finally, you could use ProGuard but hey! some k aren't that much this days, I wouldn't worry for adding some "fat" to your app as long it makes it better, of course there is always room for improvement yet remember that you are not in a java4k or stuff like that :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With