القائمة الرئيسية

الصفحات

android-tips-tricks

Image

Show some ❤️ and star the repo to support the project

GitHub stars GitHub forks GitHub watchers GitHub followers
Twitter Follow

Featured in

Android Weekly AndroidDev Digest awesome-android
Also included in
Cheatsheet about tips and tricks for Android Development
This is a simple set of tips and tricks regarding Android Development which I have gathered from various sources. It helps me direct other android devs in my community regarding stuff each android dev should know about. It is also there for me to keep track of anything I either learn on my own or from other sources now and then when browsing the internet.
Contributions are always welcome, hoping people will help me in growing this. To contribute, simply open up a PR with the changes.

Index

Know Your Tools

Android Studio

  • Code faster by using keyboard shortcuts
    DescriptionMacLinux/Win
    Lookup IDE commands / ActionsCmd Shift ACtrl Shift A
    Open ClassCmd OCtrl O
    Open FileCmd Shift OCtrl Shift N
    Open recently edited fileCmd Shift ECtrl Shift E
    Open SymbolCmd Opt OAlt Shift N
    Open recently used fileCmd ECtrl E
    Last Edited LocationCmd Shift BackspaceCtrl Shift Backspace
    Find Usage in persistent windowOpt F7Alt F7
    Find Usage in floating windowCmd Opt F7Ctrl Alt F7
    Format the code with proper IndentationCmd Opt LCtrl Alt L
    Surround WithOpt Cmd TAlt Ctrl T
    Open TerminalOpt F12Alt F12
    Generate Setter/GettersCmd NAlt Ins
    Find ClassCMD OCtrl N
    Refactor/RenameShift F6Shift F6
    Quick FixOpt EnterAlt Enter
    Goto DefinitionCmd BCtrl B
    Show parameters for selected methodCmd PCtrl P
    Refactor ThisCtrl TCtrl Alt Shift T
    Stop ProcessCmd F2Ctrl F2
    Search EverywhereShift ShiftShift Shift
    Select Methods to OverrideCtrl OCtrl O
    Delete LineCmd BackspaceCtrl Y
    Duplicate LineCmd DCtrl D
    Grow/Shrink selection from cursorOpt Up/Down Arrow keyShift Ctrl W
    Multicursor SelectionCtrl GAlt J
    Complete Keymap Guide : Linux/Win | MacOSX
  • Use plugins to become more efficient
    1. The plugin basically will annoy the hell out of you by showing you a big screen overlay with the key combination you should have used, if you used your mouse to execute some command to a level when you basically would start using the key combination just to avoid KeyPromoter annoying you all the time. It also has some useful features, like it will prompt you to create a key binding for a command whenever an action does not have a key binding and you have used it 3 times using your cursor. [ Old Version: KeyPromoter]
    2. Provides actions for text manipulation such as Toggle case, encode/decode, sorting,
    3. Add Sort Lines action in Edit menu to sort selected lines or whole file if the selection is empty.
    4. Provides static byte code analysis to look for bugs in Java code from within Android Studio
    5. The plugin that provides on-the-fly feedback to developers on new bugs and quality issues injected into Java, JavaScript and PHP code.
    6. The plugin provides both real-time and on-demand scanning of Java files from within Android Studio.
    7. The plugin that adds ADB commands to Android Studio and IntelliJ such as ADB Uninstall App, ADB Kill App, ADB Restart App, etc
    8. The plugin which helps you find and implement the code you require in an instant.
    9. The Dagger IntelliJ plugin creates visual connections between a @Inject object and the @Provides method that creates it.
    10. This plugin extends the built-in JVM debugger with capabilities to explore objects in the JVM heap during a debug session.
    11. Plugin which generates Android Parcelable boilerplate code for you.
  • Use Live Templates in Android Studio
    • newInstance - Generates the static newInstance function inside a Fragment
    • Toast - Generates Toast.makeText(context, "", Toast.LENGTH_SHORT).show();
    • fbc - findViewById with cast
    • const - Define a android style int constant
    • logd - Generates Log.d(TAG, "");
    • logm - Log current method name and its arguments.
    • logr - Log result of the current method
    • logt - static logtaf with current classname
    • psf - public static final
    • sout - Prints a string to System.out
    • soutm - Prints current class and method names to System.out
    • soutp - Prints method parameter names and values to System.out
    • visible - Set view visibility to VISIBLE
    • gone - Set view visibility to GONE
    • noInstance - private empty constructor to prohibit instance creation
  • Postfix code completion in Android Studio
    Android Studio/IntelliJ havea special kind of code completion which allows you to write code specific to a field
    • <expr>.null will auto complete to if(<expr> == null)
    • <expr>.notnull will auto complete to if(<expr> != null)
    • <expr>.var will auto complete to T name = <expr>
    • <expr>.field will auto complete to create a global field variable field = <expr>
    • <ArrayExpr>.for will auto complete to for(T item : <Arrayexpr>)
    • <ArrayExpr>.fori will auto complete to for(int i = 0; i < <Arrayexpr>.length; i++)
    • <ArrayExpr>.forr will auto complete to for(int i = <Arrayexpr>.length - 1; i > 0 ; i--)
    Complete list of available postfix code completion can be found at Settings → Editor → Postfix Templates

Emulator

Apart from using physical devices, one should use emulators as they are as of now easy to manage and equivalently powerful.

Vysor

This one needs special mention due to how useful it is. It basically is a window to your device i.e it streams and allows you to interact with your physical device on your laptop. Very useful when you are demoing your app during a presentation. You can interact with your physical device and it will be shown right in your laptop screen. It has a paid/free version, paid version is totally worth buying.

scrcpy

It is basically used to display and control your Android device and is the open source equivalent of Vysor. The good folks atGenymotion built this tool and then open sourced it (Open Source FTW).

DeskDock

Yes, vysor was great, but if you want to share your keyboard and mouse directly to your Android device, then this app is for you. It enables you to control your Android device as if it was part of your desktop computer. The FREE version includes the use of computer mouse, while the PRO version includes features such as use of keyboard. This is useful where you can test your app without your hands ever leaving your keyboard.

ADB SHELL

Few handy commands you can use to interact with emulator/device, through terminal.
DescriptionCommand
List all connected devicesadb devices
Install an application on device
-s to install on the SD Card
-g to grant all permissions listed in the manifest[More Info]
adb install -r ~/application.apk
Uninstall an applicationadb uninstall your.app.package
Download a file from deviceadb pull /sdcard/file.ext
Upload a file to a deviceadb push file.ext /sdcard
Print all installed packages on deviceadb shell pm list packages -f
Clear Application dataadb shell pm clear your.app.package
Toggle Data for deviceadb shell svc data disable
Toggle Wifi for deviceadb shell svc wifi enable
Location of Device
- High accuracy: gps,wifi,network or gps,network (if you want the wifi)
- Battery saving: wifi,network or network only
- Device only: gps
adb shell settings put secure location_providers_allowed gps
Reset all granted permissionsadb shell pm reset-permissions -p your.app.package
Reset a specific permissionadb shell pm revoke your.app.package android.permission.WRITE_EXTERNAL_STORAGE
Broadcast Actionsadb shell am broadcast -a 'my_action'
Simulating Android killing your app in the backgroundadb shell am kill
Take a Screenshotadb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screenshot.png
Launch an installed app using its package nameadb shell monkey -p com.yourapp.packagename 1

Make better choices while coding

  • Setup handy adb aliases for your terminal [Ref Link]
    Append the below Aliases to your ~/.bashrc or ~/.zshrc file, save and restart the terminal. Once saved, use them as show in Usage column
    # Take a screenshot
    # Usage: screenshot
    alias screenshot="adb exec-out screencap -p > screen-$(date -j "+%s").png"

    # Fire an intent
    # Usage: startintent https://twitter.com/nisrulz
    alias startintent="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell am start $1"

    # Install Apk
    # Usage: apkinstall ~/path/to/apk/App.apk
    alias apkinstall="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X install -r $1"

    # Uninstall an app
    # Usage: rmapp com.example.demoapp
    alias rmapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X uninstall $1"

    # Clear all data of an app
    # Usage: clearapp com.example.demoapp
    alias clearapp="adb devices | tail -n +2 | cut -sf 1 | xargs -I X adb -s X shell pm clear $1"

    # Launch your debug apk on your connected device
    # Execute at the root of your android project
    # Usage: launchDebugApk
    alias launchDebugApk="adb shell monkey -p `aapt dump badging ./app/build/outputs/apk/debug/app-debug.apk | grep -e 'package: name' | cut -d \' -f 2` 1"
  • Use OkHttp over HttpUrlConnect
    HttpUrlConnect suffers from quite some bugsOkhttp solves them in a more elegant manner. [Reference Link]
  • Reference local aar files as below [Stackoverflow Ref]
      dependencies {
    compile(name:'nameOfYourAARFileWithoutExtension', ext:'aar')
    }
    repositories{
    flatDir{
    dirs 'libs'
    }
    }
  • Use Pidcat for a better log reading experience
  • Use some Version Control System(VCS) like Git
  • It is a standalone tool for Android Devs used to browse any Android executable and show important info such as class interfaces and members, dex counts and dependencies
  • Use Stetho
    Debug your android apps using Chrome Dev Tools. Includes tools like Network Monitor, Shared Preference explorer etc.
  • A tool to analyze battery consumers using Android "bugreport" files.
  • Always use a constant version value like "1.2.0"
    Avoid using + when specifying the version of dependencies.
    • Keeps one secured from unexpected API changes in the dependency.
    • Avoids doing an extra network call for the checking latest version of each dependency on every build.
  • Use Vectors instead of PNG
    If you do have to use png, compress them. Take a look at TinyPNG.
  • Use proguard
    android {
    ...
    buildTypes {
    release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    }
    }
  • Use shrinkResources
    android {
    ...
    buildTypes {
    release {
    shrinkResources true
    minifyEnabled true
    ...
    }
    }
    }
  • Gradle memory >= Dex memory + 1Gb
  • Split your apk using gradle when using Native code, do not bundle all of em together and ship!.. coz that will make you evil
    defaultConfig {
    ...

    ndk {
    abiFilters "armeabi", "armeabi-v7a", "mips", "x86"
    }
    }

    //Split into platform dependent APK
    splits {
    abi {
    enable true
    reset()
    include 'armeabi', 'armeabi-v7a', 'mips', 'x86' //select ABIs to build APKs for
    universalApk false //generate an additional APK that contains all the ABIs
    }
    }

    // map for the version code
    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'mips': 5, 'x86': 8]

    // Rename with proper versioning
    android.applicationVariants.all { variant ->
    // assign different version code for each output
    variant.outputs.each { output ->
    output.versionCodeOverride =
    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) *
    1000000 +
    android.defaultConfig.versionCode
    }
    }
  • Learn about some architecture such as MVP or Clean
  • Try to understand and follow TDD (Test Driven Development)
  • To force re-download of dependencies
    ./gradlew --refresh-dependencies
  • To exclude a certain task from being run by gradle
    Suppose you want to exclude the task javaDoc then use -x option followed by the task name, i.e javaDoc in this case.
    ./gradlew clean build -x javaDoc
  • To have the each subproject script name match that of the project name
    Then add this line in settings.gradle
    rootProject.children.each{
    it.buildFileName = it.name + '.gradle'
    }
  • Follow the DRY principle DRY = Do not Repeat Yourself
  • With the speed android dependencies update, sooner or later you are going to encounter some sort of dependency conflict. The solution is making use of Dependency Resolution. Official Reference
  • Use different package name for non-release builds
      android {
    buildTypes {
    debug {
    applicationIdSuffix '.debug'
    versionNameSuffix '-DEBUG'
    }

    release {
    // ...
    }
    }
    }
  • Make use of custom gradle tasks in your build.gradle files
    Android uses Gradle as its build system, which actually allows one to make a lot of things easy by creating tasks to automate things. This reddit post enlists a lot of such useful gradle scripts
  • Use a proper .gitignore in your Android Projects, Check it here
  • Use LeakCanary to detect memory leaks in your app - Its a memory leak detection library for Android and Java.
  • Speed up your gradle builds in Android Studio 2.3+
    • Switch to gradle 3.4.1
      Run this inside your project folder to update your gradle wrapper
      ./gradlew wrapper --gradle-version 3.4.1 --distribution-type all
    • Set the below property in your global gradle.properties file
      android.enableBuildCache=true
  • Stop a running gradle build process
    ./gradlew -stop
  • Enable gradle to automatically download missing platforms in android sdk
    Set the below property in your global gradle.properties file
    android.builder.sdkDownload=true
    This is an experimental option and it only downloads build tools and platforms, but doesn't actually update Google or Support repository [Bug Ref]
  • Donot include both jcenter() & mavenCentral() in your build.gradle file
    JCenter is a superset of MavenCentral. [Ref tweet]
  • Clear your gradle cache if you think that bundled support and google play services lib in android sdk are inconsistent
    • Goto ~/.gradle/caches/ and delete everything inside the cache folder.
    • Open SDK Manager and resync all support libs and google play services
    • Next re-sync your project
    • Everything should become consistent and functional.
  • Setup Android Studio to fail build if code contains //STOPSHIP [Ref Link]
    To enable the //STOPSHIP lint check, in your build.gradle
    android {
    ...
    lintOptions {
    abortOnError true
    fatal 'StopShip'
    }
    }
    If you have a //STOPSHIP comment in your code, this will cause an error to be thrown when a release apk is generated.
    You can turn on //STOPSHIP highlighting in Android Studio (isn't enabled by default) in
    Preferences > Editor > Code Style > Inspections.
    Search for STOPSHIP to find the correct setting.
  • Use alfi to find the gradle dependency statement for a library
    Its basically the command line version of Gradle, Please which is a web hosted.
    • Run
      alfi name_of_library
    • Copy the desired library
    • Paste in your build.gradle
  • Use dryrun to test a library directly
    • Just Run
      dryrun REMOTE_GIT_URL
  • Output unit tests directly to the console [Ref Link]
    A small neat trick to see Android unit tests logging results as they happen in the terminal.
    android {
    ...
    testOptions.unitTests.all {
    testLogging {
    events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
    outputs.upToDateWhen { false }
    showStandardStreams = true
    }
    }
    }
  • Make your builds faster by building offline [Ref Link]
    The --offline flag tells gradle to always use dependency modules from the cache, regardless if they are due to be checked again. When running offline, gradle will never attempt to access the network to perform dependency resolution. If required modules are not present in the dependency cache, build execution will fail.
    • Assembling develop debug at full speed:
      ./gradlew assembleDevelopDebug --offline
    • Running your unit tests at full speed:
      ./gradlew test --offline
  • Use an abtracted Logger class
  • If you want to automatically initialize your library, use a Content Provider [Read how Firebase does it - Ref Link]
  • Reduce installed app size with "android:extractNativeLibs:false" in <application> [Ref Link]
    This will essentially prevent the system from creating a second copy of the .so files and fix the System.loadLibrary call so it’s able to find and open native libs straight from the APK, no code changes on your part required.
  • Selectivily execute a specific method in Android Studio [Ref Link]
    Image
  • Did you get one of these Google Play Developer Policy Violation Emails? Worry not, generate a Privacy Policy for your android app [Ref ink]
  • Define a variable at build time In your build.gradle
    android{
    defaultConfig {
    ...
    buildConfigField "String", "SERVER_ENDPOINT", '"http://www.myendpoint.com"'
    buildConfigField "int", "FOO", "52"
    buildConfigField "boolean", "LOG", "false"
    ...
    }
    }
    and then use it in code as BuildConfig.SERVER_ENDPOINTBuildConfig.FOO,BuildConfig.LOG
  • Calculate the version code and version name in your build.gradle manually, based of version values In your app'sbuild.gradle
    versionMajor = 0
    versionMinor = 0
    versionPatch = 0
    versionBuild = 1

    verCode = versionMajor _ 1000000 + versionMinor _ 10000 + versionPatch \* 100 + versionBuild
    verName = "${versionMajor}.${versionMinor}.${versionPatch}"

    // Use
    android{
    defaultConfig {
    ...
    versionCode verCode
    versionName verName
    ...
    }
    }
  • Calculate the version code and version name in your build.gradle automatically, based on git information
    Note: These functions go specifically inside the app's build.gradle and cannot be used with ext.
    In your app's build.gradle
    // Version code is calculated as the number of commits from last commit on master
    def getVersionCode = { ->
    try {
    def code = new ByteArrayOutputStream()
    exec {
    commandLine 'git', 'rev-list', 'HEAD', '--count'
    standardOutput = code
    }
    return Integer.parseInt(code.toString().trim())
    } catch (exception) {
    return "1";
    }
    }

    // Version name is Last Tag Name + No. of commits form last Tag + short git sha
    def getVersionName = { ->
    try {
    def stdout = new ByteArrayOutputStream()
    exec {
    commandLine 'git', 'describe', '--tags', '--dirty'
    standardOutput = stdout
    }
    return stdout.toString().trim()
    } catch (exception) {
    return "0.0.0.1";
    }
    }

    // Use
    android{
    defaultConfig {
    ...
    versionCode getVersionCode()
    versionName getVersionName()
    ...
    }
    }
  • Get the date of build as a variable In your app's build.gradle
    // Get the date of build
    def getDateOfBuild = { -> // ISO 8601 time format
    return new Date().format("yyyy-MM-dd'T'HH:mm'Z'").toString().trim()
    }

    // then use it as a variable in BuildConfig
    android{
    defaultConfig {
    ...
    buildConfigField "String", "DATE_OF_BUILD", "\"${getDateOfBuild()}\""
    }
    }
  • Get the Git SHA as a variable In your app's build.gradle
    // Get the last Git Short Hash
    def getGitHash = { ->
    def stdout = new ByteArrayOutputStream()
    exec {
    commandLine 'git', 'rev-parse', '--short', 'HEAD'
    standardOutput = stdout
    }
    return stdout.toString().trim()
    }

    // then use it as a variable in BuildConfig
    android{
    defaultConfig {
    ...
    buildConfigField "String", "GIT_SHA", "\"${getGitHash()}\""
    }
    }
    Have a look at the Paperwork Project, which generates build info for your Android project without breaking incremental compilation
  • Activity LifeCycle [Ref Link]
    diagram
  • Tip about onSaveInstanceState()
    onSaveInstanceState() is called only when the OS decides to kill the Activity instance. It will not be called when Activity is explicitly killed i.e User pressed back button or finish() is called from code.
  • adb shell input text "keyboard text"
  • Use areNotificationsEnabled() from NotificationManagerCompat to detect whether your users blocked your Notifications [Ref Link]
  • Don't hard-code encryption keys, a simple grep for "Ljavax/crypto" reveals them in bytecode [Ref Link]
  • Intents have a limited payload size (1Mb), don't serialize and attach entire file to it [Ref Link]
  • Always copy a file before sending it as intent URI. Receiving app could edit it & send a canceled result [Ref Link]
  • Use http:// as scheme for app deeplinks, they are more universal & when app not installed drive users to a domain you own [Ref Link]
  • Use below to display your app launch time [Ref Link]
    adb shell am start -W <packagename>/. <activityname>
  • android {
    ...
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
    }
    }
  • task deployApks(type:Copy) {
    description = "Copies APKs and Proguard mappings to the deploy directory"
    def appName = "<app_name>";
    def versionDir = android.defaultConfig.versionName+"_"+android.defaultConfig.versionCode;

    println("Copies APK and Proguard to " + versionDir)

    from 'build/outputs/mapping/release/'
    include '**/mapping.txt'
    into '../.admin/deploy/' + versionDir
    rename ('mapping.txt', "${versionDir}-mapping.txt")

    from ('.') {
    exclude '**/build', '**/src'
    }

    include '*.apk'
    into '../.admin/deploy/' + versionDir
    rename ('app-release.apk', "${appName}-${versionDir}.apk")
    }
  • To enable aapt2 set below in gradle properties
    android.enableaapt2=true
  • To testout doze mode, trigger it using adb [Ref Link
    adb shell dumpsys deviceidle force-idle
  • Thumb rule regarding setting compileSdkVersionminSdkVersion and targetSdkVersion
    minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
  • Google released an option to include OSS license activity in your app, use that to attribute credits to the OSS libs in your app [Ref Link]
  • Make Android Studio render <merge> layouts correctly by specifying the layout type with the tools:parentTag attribute [Ref Link]
    diagram
  • Checkout the Background Execution Limits on Android Oreo and update your app to work with the restrictions [Ref Link]
  • To take good screenshots with clean status bar use the Demo Mode in Android [Ref Link]
    • Steps
      1. Enable Demo Mode
        adb shell settings put global sysui_demo_allowed 1
      2. Enable/disable icons by running the right command
        // display time 12:00
        adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1200

        // Display full mobile data without type
        adb shell am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 4 -e datatype false

        // Hide notifications
        adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false

        // Show full battery but not in charging state
        adb shell am broadcast -a com.android.systemui.demo -e command battery -e plugged false -e level 100
      3. Run app and take screenshots
      4. Exit demo mode once you are done
        adb shell am broadcast -a com.android.systemui.demo -e command exit
  • To record video of your android device [Ref Link]
    adb shell && screenrecord /sdcard/download/fileName.mp4
    Hit Ctrl+C to exit/stop recording
    Recorded video file is saved at the location mentioned in the command on the device itself.
  • Use Dao inheritance to reduce the amount of boilerplate code [Ref Link]
  • Instead of using getActivity() in fragment, keep a habit of getting context from onAttach(). [Ref Link]
  • Avoid setting a background in every view/fragment as it likely causes overdraw. [Ref Link]
  • View.getWidth() = 0? That's because your view hasn't been layout yet, use globallayoutListener to know layout done. [Ref Link]
  • Android never kills activities, it only kills processes. When low memory the lowest priority ranked will be killed.[Ref Link]
  • Use -whyareyoukeeping class com.jeroenmols.MyClass to figure out why certain a class wasn't removed.[Ref Link]
  • Use certificate pinning to resist impersonation by attackers using mis-issued or otherwise fraudulent certificates, when making requests from your app. [Ref Link]
  • Do download the latest emulator using CLI
    cd <android_sdk>/tools/bin
    ./sdkmanager --channel=3 emulator
    To check the version of emulator, use ./sdkmanager --channel=3 emulator
  • Cleanup your Gradle caches by deleting files not accessed within the last month [Ref Link]
    find ~/.gradle -type f -atime +30 -delete
    find ~/.gradle -type d -mindepth 1 -empty -delete
    To check the size of your gradle cache, run: du -sh ~/.gradle
  • Remove all debug log statements from the release build using the below proguard rules. (app's build.gradle should haveminifyEnabled true set for this to work)
    # Remove all debug logs
    -assumenosideeffects class android.util.Log {
    public static *** d(...);
    }
    The above snippet is usually appended to contents of app/proguard-rules.pro file
  • tl;dr
    • If you need code to be very performant integer constants may be the way to go
      public class Operator {
      public static final int ADD = 1;
      public static final int SUBTRACT = 2;
      public static final int MULTIPLY = 3;
      public static final int DIVIDE = 4;
      }
    • Use Enums because
      • Are type-safe, so you can only use valid enum types
      • Provide better code readability
      • Can implement interfaces
      • Support polymorphic behavior
      • In some really trivial cases, Proguard can optimize Enums into integer constants for you [Ref Link]
      • Performance difference rarely makes a difference.
      public enum Operators {
      Add, Subtract, Multiply, Divide
      }
  • The string resource android.R.string.yes doesnot yield string "Yes" instead it yields "Ok". Similarly the string resourceandroid.R.string.no doesnot yield string "No" instead it yields "Cancel" [Ref Link]
    string resource
  • Don’t want generated files in your AS search results? Go to Preferences -> File Types -> Ignore files and foldersand add the pattern to ignore - e.g. *.dex;*.class; [Ref Link]
  • If you uncheck “Suspend” and check “Evaluate and Log” in breakpoint menu, the breakpoint will print evaluated statement into the uncluttered “Console” window. No need for recompile due to added Log.d statements anymore [Ref Link]
    Breakpoint Logs
  • To measure how long a method took to execute, you can use TimingLogger class. [Ref Link]
    • Typical Usage
      TimingLogger timings = new TimingLogger(TAG, "methodA");
      // ... do some work A ...
      timings.addSplit("work A");
      // ... do some work B ...
      timings.addSplit("work B");
      // ... do some work C ...
      timings.addSplit("work C");
      timings.dumpToLog();
    • Output
      D/TAG     ( 3459): methodA: begin
      D/TAG ( 3459): methodA: 9 ms, work A
      D/TAG ( 3459): methodA: 1 ms, work B
      D/TAG ( 3459): methodA: 6 ms, work C
      D/TAG ( 3459): methodA: end, 16 ms
  • If you're working with Android Things and you don't have an extrenal screen for your device, install scrcpy and use it to see what's going on your Android IoT device. It works a charm over wireless adb. [Ref Link]
  • Android Studio has this weird behaviour that it allows to edit its default code style, which leads to a weird side-effect. If you open your pre-setup project(with set codestyle and copyright configs) in Android Studio it will delete all pre-setup codestyle and copyright profile in this project. This is every much evident if you checked in your configs into git for sharing purpose, which is lost immediately as soon as you open the project
    deleted:    .idea/codeStyles/Project.xml
    deleted: .idea/codeStyles/codeStyleConfig.xml
    deleted: .idea/copyright/profiles_settings.xml
    deleted: .idea/copyright/copyright.xml
    To fix that please follow along as below: [All thanks to Said Tahsin Dane for the solution]
    • We first need to verify that your Default codestyle isn't modified. To check that please open Android Studio with any project except your pre-setup(with set codestyle and copyright configs) project. Then navigate toPreferences>Edior>Codestyle and check if your code scheme has Default in BLUE color (this means it is modified).
      modified_default
    • However if it is not colored BLUE, you are good and you can go ahead to open your pre-setup(with set codestyle and copyright configs) project and everything should be pre-setup for you.
    • If it is modified (colored BLUE), then click on the cog icon and select Restore Default
      restore_default
    • After you hit that option, simply accept the change
      accept_change
    • Once done, you will see your Default is no more colored BLUE or modified, which means you are good
      unmodified_default
    • Now simply go ahead and open your pre-setup(with set codestyle and copyright configs) project and everything should be pre-setup for you.
  • If you add android:sharedUserId to an already published app, the app data will be cleared for all users that install your upgrade (because Android changes the process). So if you ever intend to use it, you must add it before publishing your app [Ref Link]
  • When opening up methods for testing, use otherwise to still hide it from code complete.[Tweet LinkRef Link]
    making_methods_visible_for_testing
  • You can group your recent Android Studio projects, and add icons to them [Ref Link]
    group_recent_projects
  • Only build a single configuration to speed up debug builds. [Ref Link]
    build_single_config
  • Avoid the annoying jump to Design tab while editing XML. Prefer XML editor under Settings [Ref Link]
    set_xml_as_preferred
  • Reduce installed app size with android:extractNativeLibs="false" in [Tweet LinkRef Link]
  • Run a single unit test from the command line using the --tests option e.g: ./gradlew testDebugUnitTest --tests "*.MainPresenterTest" . Use * to avoid typing the entire package name. [Ref Link]
  • Improve Android Studio code inspections with Thread annotations [Tweet LinkRef Link]
  • Use adb to put a phone into doze mode for testing [Tweet LinkRef Link]
  • Get faster gradle builds by only using one resource configuration for your development builds [Ref Link]
    android {
    ...
    productFlavors {
    dev {
    ...
    // The following configuration limits the "dev" flavor to using
    // English stringresources and xxhdpi screen-density resources.
    resConfigs "en", "xxhdpi"
    }
    ...
    }
    }
  • Use areNotificationsEnabled() from NotificationManagerCompat to detect whether your users blocked your Notifications [Tweet LinkRef Link]
  • Activity.runOnUiThread is just a convenient wrapper of Handler.post; don't pass around Activity just so you can use it. [Ref Link]
  • Define your interfaces with the highest possible option that will suffice. Don't use an Activity when a Context will do. [Ref Link]
  • If you're not building a replacement for the dialer, use ACTION_DIAL not ACTION_CALL to initiate a call. [Ref Link]
  • Specifying buildToolsVersion in your build.gradle files is optional when using Android plugin 3.0.0 or later. By default the plugin uses the minimum version of the build tools required by the version of the plugin you're using. [Tweet LinkRef Link]
    dont_specify_buildtoolsversion
  • You can insert variables into AndroidManifest defined in build.gradle [Tweet LinkRef Link]
    inject_vars_in_manifest
  • Requesting updates from a system service may drain battery, so register for updates in onResume and unregister in onPause. [Ref Link]
  • Hierarchy Viewer won’t run on prod devices, if however u want to run it then follow below steps [Tweet LinkRef Link]
    running_hierarchy_viewer
  • Variable and init block declaration order in Kotlin, actually matters :) if you want to use a variable inside init {} initialize it before it.
  • When comparing intents it does not compare any extra data included in the intents [Tweet LinkRef Link]
  • To show a ringtone picker to the user, use the ACTION_RINGTONE_PICKER intent to launch the picker as a subactivity. [Ref Link]
  • Want to remove focusState on an item in GridView? Try: android:listSelector="#00000000" [Ref Link]

Tips regarding UI/UX

  • Motion
    • Material Design uses real-world metaphors as its foundation. Objects in the real world don't move linearly, they move in curved paths and accelerate and decelerate according to the motion's properties.
    • As such, motion should also use such properties and animate objects so that the motion feels natural rather than forced
    • For example, a car leaving the screen in a movie starts off slowly, then accelerates till it's out of the frame. Similarly, views should be interpolated using classes like AccelerateInterpolator, FastOutSlowInInterpolator, etc. [More Info]
    • When changing the visibilities of views, if you add android:animateLayoutChanges="true" to the parent, you get a nice little animation for free. [Ref Link]
  • Typography
    • While custom typefaces can be used for branding, it is essential to stick to Roboto and Noto if possible, especially for body text, due to their clarity and optimistic nature.
    • Roboto covers Latin, Greek and Cyrillic extended scripts, with Noto filling in for other language scripts [More Info]
    • Weight balancing is an important aspect of typography, the fundamental concept of which is that the larger a typeface is, the less its weight should be so that it doesn't appear too thick and balances its weight with smaller typefaces of higher weights
    • Typography should align to a 4dp baseline grid, and maintain a minimum contrast ratio of 4.5:1 based on luminance values, with a recommended ratio being 7:1.
    • The ideal reading length for large blocks of text is 40 to 60 characters per line. Anything less is too narrow and anything more is too wide.
  • Icons
    • Icons should be designed at 48dp, with 1dp edges, which equates to
      • 48px by 48px at mdpi
      • 72px by 72px at hdpi
      • 96px by 96px at xhdpi
      • 144px by 144px at xxhdpi
      • 192px by 192px at xxxhdpi
    • An additional icon of 512px by 512px should be designed for use on Google Play
    • Material icons, in addition to the base icon, should contain the following important elements
      • 1dp tinted edge at the top
      • 1dp shaded edge at the bottom
      • Contact shadow - a soft shadow around all edges of raised elements
      • Finish - a soft tint to provide surface lighting, fading from upper life to lower right [More Info]
  • Ripples
    • When implementing Ripple Effect use ?attr/selectableItemBackground instead of ?android:attr (Ref)
    • When implementing Ripples contained within the view like Button, use (Ref)
      android:background="?attr/selectableItemBackground"
    • When implementing Ripples that extend beyond the view's bounds like ImageView: (Ref)
      ?attr/selectableItemBackgroundBorderless
  • Other Points to Note
    • Views should be aligned to Material Design's 8dp baseline grid and the keylines when possible. This gives the UI a sense of structure and hierarchy. [More Info]
    • If you plan on keeping a reference to any ViewGroup (LinearLayout, FrameLayout, RelativeLayout, etc.), and you don’t want to use any methods specific to this particular type of Layout, keep it as a ViewGroup object. [More Info]
    • While picking an accent color (if the brand already has one), pick a color complementary to the primary color so that the contrast is high enough

Tips if you use Kotlin

Other Resources

Extra : Android Libraries built by me

  • EasyDeviceInfo - Enabling device information to be at android developers hand like a piece of cake!
  • Sensey - Android library to make detecting gestures easy
  • PackageHunter - Android library to hunt down package information
  • Zentone - Easily generate audio tone in android
  • RecyclerViewHelper - RecyclerViewHelper provides the most common functions around recycler view like Swipe to dismiss, Drag and Drop, Divider in the ui, events for when item selected and when not selected, on-click listener for items.
  • StackedHorizontalProgressbar - Android Library to implement stacked horizontal progressbar
  • QREader - A library that uses google's mobile vision api and simplifies the QR code reading process
  • ScreenShott - Simple library to take a screenshot of the device screen, programmatically!
  • EvTrack - Android library to make event and exception tracking easy
  • OptimusHTTP - Android library that simplifies networking in android via an async http client
  • ShoutOut - Android library for logging information in android
  • Lantern - Android library handling flashlight for camera and camera2 api. Added support for handling display/screen light.

Translations

If you would like to contribute by translating this doc, please do so by sending a PR which follows the below points
  • Make sure the filename is README-language.md i.e README-English.mdREADME-Greek.md, etc.
  • The original content/formatting is retained in the translated doc.
  • Check for grammar and spelling mistakes before hand.

Credits

This curated cheatsheet includes tips and tricks that I have been following in my workflow as well as those being suggested/followed by other android devs worldwide.I have tried to add direct links wherever I could remember, giving people due credit who have explained the concepts. If you think I have missed any, then either send a PR or open an issue and I will fix it asap.
If you found this cheatsheet helpful or you learned something today and want to thank me, consider buying me a cup of ☕️
  • PayPal
  • Bitcoin Address: 13PjuJcfVW2Ad81fawqwLtku4bZLv1AxCL

License

Copyright 2016 Nishant Srivastava

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
هل اعجبك الموضوع :

Commentaires

التنقل السريع