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...
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 haveR
, which is API level30
, which is Android11
, which is very confusingActivity
andView
still growing strong 💪AsyncTask
andIntentService
are deprecated, good bye old friends- 24 entries added and deprecated within the same
R,30,11
(search for the-+
)
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 systemSettings
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 onlyALIGN_BOTTOM
andALIGN_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
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?
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...
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:
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?
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.
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
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̹͘̕thu
siͫ͡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.
This tutorial will show how to achieve complex animations in a clean and easy way in just few lines of code.
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
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!
@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.
Newton's Cradle Drawable (Tumbleweed Android)
Implementation steps to create Newton's Cradle drawable for Android.
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...
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.