Android: Using "Die with me" app without killing the phone's battery

Die with me is a chat app which can be used only when the phone’s battery is below 5%. Here is a fun way to use the app without draining your phone’s battery. Connect the phone via ADB or start Android emulator and fake the battery level to 4%. Bash 1 2 sudo pip3 install adb-enhanced adbe battery level 4 # Set battery level to 4% And now, you can use the app. After playing with the app, reset the battery level with, ...

Circle CI vs Travis CI

Update: As of Mar 2022, I recommend everyone to use GitHub Actions I maintain a somewhat popular Android developer tool ( adb-enhanced ). The tool is written in Python, supporting both Python 2 and 3. Testing the tool requires both Python runtime as well a running Android emulator. I, initially, used Travis CI for setting up continuous testing of this tool. Later, I felt that Travis CI was too slow and when I came across Circle CI, I decided to give it a try. As of now, both Travis and Circle CI are used for testing. Here is what I learned from my experience.

Android Security: Don't leave WebView debugging enabled in production

WebView debugging can be enabled via “WebView.setWebContentsDebuggingEnabled(true)”. Leaving WebView debugging enabled in production Android apps is a bad idea. Anyone who gets hold of the unlocked phone can access the app’s data forever.

Android: Fragment related pitfalls and how to avoid them

Don’t use platform fragments (android.app.Fragment), they have been deprecated and can trigger version-specific bugs. Use the support library fragments ( android.support.v4.app.Fragment) instead. A Fragment is created explicitly via your code or recreated implicitly by the FragmentManager. The FragmentManager can only recreate a Fragment if it’s a public non-anonymous class. To test for this, rotate your screen while the Fragment is visible. FragmentTransaction#commit can fail if the activity has been destroyed. “java.lang.IllegalStateException: Activity has been destroyed” Why - This can happen in the wild where say right before FragmentTransaction#commit() executes, the user gets a phone call and your activity is backgrounded and destroyed. How to trigger manually - The easy way to manually test this is to add a call to Activity#finish() right before FragmentTransaction#commit. Fix - Before doing FragmentTransaction#commit(), check that the activity has not been destroyed - Activity#isDestroyed() should return false. ...

Android: Handling JPEG images with Exif orientation flags

A JPEG file can have Exif metadata which can provide the rotation/translation field information for a raw JPEG image. So, a landscape raw JPEG image could actually be a portrait because it’s EXIF orientation could be set to ORIENTATION_ROTATE_90 , the best way to handle such scenarios is to either use a library like Picasso or Glide or at least learn from them. Here is a piece of code from Picasso which loads a JPEG as an in-memory bitmap and performs the right translation/rotation. ...

Mac OS: App Translocation and Android Studio updates failure

I installed Android Studio via homebrew “brew cask install android-studio” as a part of my automated Mac OS setup . Recently, Android Studio prompted me that an update is available. When I accepted to update, it failed with an error “Studio does not have write access to /private/var/folders/wt/rjv6_wcn4f97_2nth7fqftqh0000gn/T/AppTranslocation/19A80F28-865B-41FC-AA87-B8E43C826FCB/d/Android Studio.app/Contents. Please run it by a privileged user to update.” This error was confusing; I was running Android Studio as myself, a nonprivileged user and the same user owned this directory. Googling it a bit for AppTranslocation took me here . ...

Cross-language bridge error handling: JS-to-Java Example

All languages have certain semantics for dealing with error cases. C deals with them by setting error codes. Java deals with them by throwing exceptions. JavaScript deals with them by throwing exceptions as well but unlike Java, it does have any concept of checked Exceptions. The JS interpreter just stops. And this has some interesting implications in hybrid scenarios like a Webview based app. Consider a simple Android app where most of the code is in JavaScript but is making a request to Java layer. ...

Testing resumable uploads

The core idea behind resumable upload is straightforward if you are uploading a big file, then you are going to encounter users in the network conditions where they cannot upload the file in a single network session. The client-side code, to avoid restarting the file upload from the beginning, must figure out what portion of the file was uploaded and “resume” the upload of the rest. How to do resumable upload Before starting the upload, send a unique ID generated from the file contents to the server like MD-5 or SHA-256. The server decides and declares what the format of that unique ID is. Next, the server responds with an offset which indicates how many bytes server already has. The client uploads rest of the bytes with a Content-Range header . ...

Architecting Android apps for emerging markets

This is a long post. It covers several decisions like API version, distribution beyond play store, UI & network performance, and minimizing RAM, disk, and battery usage.

Introducing adb-enhanced: A swiss army knife for Android development

Android development requires tons of disconnected approaches for development and testing. Consider some scenarios To test runtime permission - Go to Settings -> Applications -> Application info of the app you are looking for and disable that permission. To test a fresh install - adb shell pm clear-data com.example To test your app under the battery-saver mode - turn on the battery saver mode by expanding the notification bar To stop the execution of an app - kill it via activity manager, adb shell am kill com.example To test your app under doze mode - first, make the device believe that it is unplugged via “adb shell dumpsys battery unplug”, then, make it think that it is discharging via “adb shell dumpsys battery set status 3”, and then enable doze mode via “adb shell dumpsys deviceidle force-idle”. And don’t forget to execute a set of unrelated complementary commands once you are done to bring the device back to its normal state. To see the overdraw of the app - Go to the developer options and enable/disable it there. Over time, this became a significant mental burden that I first wrote some of these flows in a text file and then converted them to automated shell scripts. But when even that felt insufficient, I created a tool for myself called adb-enhanced. ...