# 11 Ways To Optimize App Performance Part 2

In the **last blog**, we delved into code optimization, UI/UX, network, storage optimisation, and using Android Jetpack as a means to speedup your app performance.

In this article we will look at some more ways to optimize app performance.

## Optimize battery usage

Optimizing battery usage enhances user experience by reducing power consumption and prolonging battery life. Some key aspects to consider when optimizing battery usage in your android app are as follows

### Use Doze, App Standby, and other power management features

[Doze and App Standby](https://developer.android.com/training/monitoring-device-state/doze-standby) are android features that help conserve battery by putting apps in a low-power state when the device is idle. To ensure your app works well with these features, avoid performing unnecessary background tasks and adapt to the power-saving restrictions. Test your app to make sure it behaves correctly under these power management modes.

![⚠️ Over-optimization can lead to reduced app functionality or a less responsive app if not handled carefully. It's essential to strike a balance between power efficiency and app performance.](https://cdn.hashnode.com/res/hashnode/image/upload/v1680804154774/29b5714a-ba89-440f-a4e0-e3ba56f9dfb3.png align="center")

You can use the [PowerManager](https://developer.android.com/reference/android/os/PowerManager) class to check if the device is in Doze mode or not:

```kotlin
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
val inDozeMode = powerManager.isDeviceIdleMode
```

### Optimize wake locks and location updates

[Wake locks](https://developer.android.com/training/scheduling/wakelock) allow your app to keep the device awake while performing critical tasks. However, excessive use of wake locks can drain the battery. Minimize wake lock usage and release them as soon as possible.

For location updates, request updates only when necessary and use appropriate location request settings, like [PRIORITY\_BALANCED\_POWER\_ACCURACY](https://developer.android.com/guide/topics/location/battery), to balance accuracy with battery consumption.

### Use JobScheduler, WorkManager, or AlarmManager for efficient background tasks

These [APIs](https://developer.android.com/guide/background) allow you to schedule background tasks to run when certain conditions are met, such as when the device is charging or connected to Wi-Fi. This can help you reduce battery consumption by avoiding running tasks when the device is on battery power.

For example, using WorkManager in Kotlin:

```kotlin
val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.UNMETERED)
    .setRequiresCharging(true)
    .build()

val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
    .setConstraints(constraints)
    .build()

WorkManager.getInstance(this).enqueue(myWorkRequest)
```

In this example, we create a `Constraints` object with specific requirements (unmetered network and charging) and build a `OneTimeWorkRequest` with these constraints. Then, we enqueue the work request using WorkManager.

> ⚠️ Over-optimization can lead to reduced app functionality or a less responsive app if not handled carefully. It's essential to strike a balance between power efficiency and app performance.

## Optimize for various devices

### Use Android Support Library or AndroidX to maintain compatibility

The Android Support Library and AndroidX provide a collection of libraries that enable backward compatibility with older Android versions and a consistent UI/UX across devices. By using these libraries, you can ensure your app runs smoothly on a variety of devices and Android versions.

For example, using AndroidX in your `build.gradle` file

```kotlin
dependencies {
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    // Add other AndroidX dependencies as needed
}
```

### Provide alternative resources for different screen densities and sizes

Android allows you to create alternative resources (such as images and layouts) for different screen densities (mdpi, hdpi, xhdpi, etc.) and sizes (small, normal, large, etc.). This ensures your app looks good and functions well on various devices with different screen characteristics.

### Test on various devices and emulators to ensure a consistent experience

To make sure your app performs well on a wide range of devices, it's crucial to test it on different physical devices and emulators. This helps you identify and fix any device-specific issues that may arise.

> 😅 Virtual machines, such as emulators, can put a strain on your system's memory if launched within your local environment, which could result in a slowdown of your development. **If you're facing this issue, you might be interested in exploring the solution we're developing at** [Dashwave](https://www.notion.so/Dashwave-Ideas-a88f7f2eaebe4b91861ce7d970554d50).

## Utilize ProGuard or R8

[ProGuard and R8](https://developer.android.com/studio/build/shrink-code) are tools that optimize, obfuscate, and shrink your Android app code. Both tools help improve app performance and reduce the app's size by removing unused code and obfuscating the remaining code to make it harder to reverse-engineer. R8 is now the default code shrinker in Android Studio, but you can still use ProGuard if you prefer.

However obfuscation can make debugging more challenging, as stack traces and error messages may be harder to understand. But tools like [Firebase Crashlytics](https://firebase.google.com/products/crashlytics?gclid=Cj0KCQjww4-hBhCtARIsAC9gR3a38eMiBZIQfPdQVdvgpwNOlehDPXjX7Rha8URuG5PYFBeyPA7MyFQaAiH4EALw_wcB&gclsrc=aw.ds) can help deobfuscate stack traces for easier debugging.

To enable R8 in your Android project, follow these steps:

1. Add the following line to the [`gradle.properties`](http://gradle.properties) file in your project:
    

```kotlin
android.enableR8 = true
```

1. Configure R8 rules by creating a file named `proguard-rules.pro` in the `app` module of your project.
    

1. Add rules to the `proguard-rules.pro` file as needed. For example, to keep a specific class from being obfuscated, you can add the following line:
    

```kotlin
-keep class com.example.myapp.MyClass { *; }
```

1. Finally, in your app module's `build.gradle` file, add a reference to the `proguard-rules.pro` file:
    

```kotlin
android {
    ...
    buildTypes {
        release {
            ...
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
```

## Keep app size small

Keeping your app's size small is essential for improving download times, reducing storage space used on the user's device, and providing a better overall user experience. Here are some ways to achieve this:

### Remove unused code, resources, and libraries

Regularly audit your codebase and remove any unused or unnecessary components. Android Studio's built-in Lint tool can help you identify unused resources.

![Code scanning workflow with the lint tool.](https://cdn.hashnode.com/res/hashnode/image/upload/v1680804209271/8cf8082a-c867-480b-9712-1afd79618e6c.png align="center")

### Use Android App Bundle (AAB)

[Android App Bundle](https://developer.android.com/guide/app-bundle) is a publishing format that allows Google Play to serve only the necessary resources for a specific device. To enable AAB, follow these steps in your app module's `build.gradle` file:

```kotlin
android {
    ...
    bundle {
        language {
            enableSplit = true
        }
        density {
            enableSplit = true
        }
        abi {
            enableSplit = true
        }
    }
}
```

Then, when you're ready to publish your app, generate an app bundle using Android Studio's `Build > Generate Signed Bundle / APK` option.

### Compress images and other large assets

Use efficient image formats like WebP or JPEG, and compress your images without losing too much quality. For other large assets, consider using formats like gzip. However, compressing assets might result in slightly lower quality, so it's essential to strike a balance between size and quality.

## Regularly update libraries and SDKs

Updating the libraries and SDKs used in your Android app is essential for staying current with performance improvements, bug fixes, and new features. Here's how you can update your dependencies

### Update dependencies in the `build.gradle` file

Periodically check for updates to your dependencies and replace the version numbers in your `build.gradle` file with the latest versions. For example:

```kotlin
dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.9.3' // Update to the latest version.
    ...
}
```

### Migrate deprecated APIs to their newer counterparts

After updating your dependencies, make sure to replace any deprecated APIs with their newer equivalents. This may involve refactoring your code or implementing new methods.

That’s it!

## Conclusion

Optimizing an android app's performance is a multifaceted process that requires attention to various strategies that we have discussed in this article series. By following them and employing the recommended practices, you can significantly enhance your app's performance, resulting in a better user experience and increased user satisfaction.

Furthermore, gathering user feedback and making data-driven decisions will ensure your app remains relevant and appealing to your target audience. By dedicating time and resources to performance optimization, you will ultimately create a more successful and enjoyable app for your users.

Thanks for reading!
