Dimitry Ivanov

Di's blog

Automatic variable name for logging

Logging variables in Java or Kotlin in most of the cases end up with duplicated content - one have to specify variable name first and then the variable itself:

Debug.i("index: $index, value: $value, direction: ${vector.direction}")
Debug.i("index: %s, value: %s, direction: %s", index, value, vector.direction);

Typing each variable twice takes time, slows down and seem to have a room for improvement. What if...

Enumerate with Live Templates

Continue

Android 11 API changes

This is a raw changelog for the Android 11 API created with the Enhance library.

  • Build.VERSION_CODES still appends new versions as letters, so now we have R, which is API level 30, which is Android 11, which is very confusing
  • Activity and View still growing strong 💪
  • AsyncTask and IntentService are deprecated, good bye old friends
  • 24 entries added and deprecated within the same R,30,11 (search for the -+)

Continue

Kotlin is even more fun now!!

The 1.4 Kotlin announcement contains multiple features. Among them there is the SAM conversion for Kotlin interfaces (previously applicable for Java interfaces only). And it's definitely a fun addition to the language. And it's really funny (try not to fun!):

fun interface Action {
  fun run()
}

As much as I fun the nice and warm fun that fills me when working with Kotlin fun, I would still like to see an expansion of emotion spectrum available though. Dear Kotlin team we still need love, friendship, honesty, truth, joy, trust, care, empathy and hope. And those, when added, can become a constant reminder for a developer to become a better person meanwhile maintaining productive and professional environment. Let's make the world a better fun!

</s>

Android 10 API changes

With the latest Enhance update to support Android 10 I decided to extract API changes that had happened on the public surface - what classes/fields/methods were added or deprecated (sometimes both! - search for the -+ sequence).

There are few things that I had noticed:

  • Activity, View and TextView are still growing, great!
  • There are 11 entities that were both added and deprecated in Android 10 (again — -+ to look up)
  • There are newly deprecated methods inside already deprecated classes (for example Fragment was deprecated in Pie (28), but all of its' methods are deprecated in Android 10)
  • Deprecation of android.preference.* (it seems that the main user of this package was system Settings app, what will it use instead - androidx artifact 🤔?)
  • NetworkInfo is deprecated (and so as a quick way to check if a device has a network connection - NetworkCallback must be used instead, which doesn't seem very convenient)
  • Build.VERSION_CODES.Q is there (check out the javadoc!)
  • DynamicDrawableSpan.ALIGN_CENTER! Previously only ALIGN_BOTTOM and ALIGN_BASELINE were available

So, here is the gist of API changes in Android 10:

android/Manifest$permission
+   ACCESS_BACKGROUND_LOCATION
+   ACCESS_MEDIA_LOCATION
+   ACTIVITY_RECOGNITION
+   BIND_CALL_REDIRECTION_SERVICE
+   BIND_CARRIER_MESSAGING_CLIENT_SERVICE
+   CALL_COMPANION_APP
-   PROCESS_OUTGOING_CALLS
+   REQUEST_PASSWORD_COMPLEXITY
+   SMS_FINANCIAL_TRANSACTIONS
+   START_VIEW_PERMISSION_USAGE
+   USE_FULL_SCREEN_INTENT
Continue

How to toggle boolean in SQLite

Okay, SQLite doesn't have a separate Boolean datatype, but it's not uncommon to use an INTEGER to store one. How can we toggle this value in a single SQL statement without retrieving stored value first?

Continue

EmotionLayout

I've stumbled upon an interesting UI effect by Chris Banes implemented with MotionLayout. Unfortunately... well. Unfortunately it's MotionLayout, so motions are defined in XML scene files sprinkled with constrains and references to views. If you haven't seen one — go ahead and see the one that defines UI effect in question. Now, there must be a simpler way...

Continue

public static void main for Android

Sometimes I find myself wanting to evaluate some Android code without launching an app on a device or an emulator (and without adding log statements in random components). For example Java has a public static void main method that can be added in any class and launched right from the IDE. Can this be done for Android?

public class MainActivity extends Activity {

    public static void main(String[] args) {
        final String input = "tel:+34 666 55 52 22";
        System.out.printf("input: %s, uri: %s%n", input, Uri.parse(input));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Unfortunately this will fail with somewhat famous exception:

Exception in thread "main" java.lang.RuntimeException: Stub!
	at android.net.Uri.parse(Uri.java:293)
	at io.noties.psvm.MainActivity.main(MainActivity.java:11)

This happens because our code is compiled with android.jar dependency (that can be found in $ANDROID_SDK/platforms/android-${version}/android.jar) that has only public API definitions. All API method signatures are present but their bodies contain a single statement: throw new RuntimeException("Stub!"). android.jar here is a runtime dependency. We still can operate on public API during development, but actual implementation is provided by a device or an emulator when an app is launched.

I labeled the java.lang.RuntimeException: Stub! as somewhat famous because you might've seen it whilst trying to launch java unit tests that contain Android code. This problem is long gone with the help of amazing Robolectric testing framework. But wait... this must mean that Robolectric has a proper android.jar with all the methods present. Can we use it?

Continue

Google Pixel

The more you think about it the more it becomes obvious that Google Pixel is a perfect name for a Google brand. Especially if you take into account the tracking pixels that are so wide-spread in web-pages you visit or emails you read. Only this time data collection is taken to a truly next level closing the gap between physical and digital world. Precise geolocation, MAC addresses of networking hardware, available Wi-Fi networks, nearby cell towers, non-stop audio recording, access to photo cameras, behavioral patterns, VPN configs and true IP addresses and much-much more were still not available to web pages. Until the true Pixel emerged...

Gradient Messenger Round 2

In the previous article we've implemented gradient background with fixed scrolling behavior. Similar effect can be seen in the Fa¢ebook Messenger app. Now it's the time to give our app some UI polish - we will add rounded corners to chat messages and introduce messages grouping. Most of the changes will happen in our custom RecyclerView.ItemDecoration which source can be found here. As a bonus point we will make our RecyclerView.ItemDecoration ready for RecyclerView.ItemAnimator animations.

Continue

Kotlin is fun!!

kotlin is fun!!

Gradient Messenger

In this article we will reproduce fixed gradient background for chat messages. Similar effect can be seen in the Fa¢ebook Messenger application. We will use custom Drawable, RecyclerView and RecyclerView.ItemDecoration.

TL;DR: browse the source code

Continue

We have everything

We have:

  • interesting tasks
  • cutting edge tech
  • cross functional teams
  • team leads
  • human resources heads
  • talent hunters
  • QA
  • product managers
  • product owners
  • vision bearers
  • keepers of team spirit
  • meetups͙
  • h̺͒acka͠t̃on͢s̚
  • f̵ree snͭacks
  • c̯ͭ̌ͤof̝ͯf͚ee
  • amazi̯͡ng openͩ off̬̽i͜ce
  • sc͊rum̂ m̱a͢ste̎rs
  • ag͘i͊le e̘n̹͘̕thusiͫ͡a͉͖̽sts
  • advͅoca̛̫̚͞ts̖͌ of wȟă͞t-not
  • n̸͂o͆̏thǐn̳g wor͑ks̈!
  • no̬thͥ̚i̕n҉̬̯gͅ wͨork͚̏͜s̵͔͡?

Complex Android animations - Tutorial

Achieving complex animations on Android might be a daunting task. Especially when an arbitrary number of views are involved and/or they have specific ordering (one-after-another, grouping, delays, etc). Using built-in ValueAnimator, ObjectAnimator, ViewPropertyAnimator or AnimatorSet would result in untangled mess of callbacks and won't be extensible, easy to tweak nor maintain.

gif

This tutorial will show how to achieve complex animations in a clean and easy way in just few lines of code.

Continue

Local Maven repository

With a little help of Gradle one can have a local Maven repository literally with a single line of code in the build configuration file:

repositories {
    maven { url 'file:///Users/me/.maven-local' }
}

It can be used to release your local artifacts also. For example, if you are using gradle-mvn-push:

if (project.hasProperty('local') {
    ext.RELEASE_REPOSITORY_URL = 'file:///Users/me/.maven-local'
}
./gradlew upA -Plocal

BTW upA here stands for uploadArchives but Gradle allows us to shorten task name a bit

Continue

Enhance Android source code for developers

It's actually a follow-up of the previous @since tag to Android source distribution. Turned out this can be done by ourselves (plus a bit more). Here is the final result:

/**
 * Called by the system when the activity changes from fullscreen mode to multi-window mode and
 * visa-versa.
 *
 * @see android.R.attr#resizeableActivity
 * @param isInMultiWindowMode True if the activity is in multi-window mode.
 * @deprecated Use {@link #onMultiWindowModeChanged(boolean, Configuration)} instead.
 * @since 7.0 Nougat (24)
 * @deprecated 8.0 Oreo (26)
 */
@Deprecated
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
    // Left deliberately empty. There should be no side effects if a direct
    // subclass of Activity does not call super.
}

TLDR: Enhance!

Continue

@since tag to Android source distribution

Some time ago I come up with simple enhancement for the Android source code that is distributed via SDK Manager: adding the @since javadoc tag to the public API.

Just imagine:

/**
* Sets a rectangular area on this view to which the view will be clipped
* when it is drawn. Setting the value to null will remove the clip bounds
* and the view will draw normally, using its full bounds.
*
* @param clipBounds The rectangular area, in the local coordinates of
* this view, to which future drawing operations will be clipped.

* @since 4.3 (18)
*/
public void setClipBounds(Rect clipBounds) {
...

Issue on the bug tracker.

Continue

Newton's Cradle Drawable (Tumbleweed Android)

gif

Implementation steps to create Newton's Cradle drawable for Android.

Continue

Square Frame Layout

A simple implementation of FrameLayout to be used in a RecyclerView with a GridLayoutManager in order to achieve square shaped layout. Does not depend on external dimensions. Will always be square even if you change spanCount at runtime.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// to be continued...
Continue

Grid items equal spacing (RecyclerView)

This is how to achieve equal spacing between grid elements and RecyclerView borders. Applicable for both GridLayoutManager and StaggeredGridLayoutManager. No modification of existing Adapter is required.

2 columns 3 columns 4 columns
Continue