Monday, January 16, 2017

Java compatibility in build.gradle

I got an email from Google asking me to update Fit Cat for Android Wear 2.0, so I tried to compile that app after I haven't touched it for a few months.

Since Android Studio evolves so quickly, I wasn't exactly surprised when I got an error:

Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been
compiled using Java 8 or above.

It asked me to add sourceCompatitbility and targetCompatitbility to Java submodules. What does that mean? After a lot of searching plus trial and error I found the answer.

In your top-level build.gradle, add this:

allprojects {
  tasks.withType(JavaCompile) {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
  }
}

Thursday, December 1, 2016

Elite Worship

Yesterday I read an article called In a world..., which talked about the problem of elite worship in the iOS community. I'm an Android developer, but I see the same problems in our community as well.

Here is how I see it:

  • People who tweet, blog, speak and open source are considered elites
  • Elites are held above the rest of the community, making it unwelcome for others

Does being loud make you a better developer?

Or, flipping the question, are people who don't share their work inherently worse? No, of course not. Unfortunately, unseen work is just that: unseen. Without external evidence, there is no way to tell if a developer is good or not, so we assume they are average. Not better, not worse.

I, too, would like to believe that we live in a meritocracy where good work is automatically recognized. But how? How do people know what you are doing if you don't tell them?

This encourages people to run up a hill and yell on top of their voice. And the people who are comfortable doing that are rewarded, are seen as "better".

However, this is not automatically lead to elite worship. Yes, there will always be some people who are more visible in the community. But that does not mean it has to be a small group who are revered above all else.

What you can do

When you see good work, point it out

One problem of elite worship is that we ended up comparing ourselves with people with more Twitter followers, more mentions in the industry newsletter, more conference talks etc and feel defeated. We can counter that by pointing out the good work we see that is not enshrined on the internet.

Here is a concrete thing you can do: When you do a code review, don't just point out the things to fix. Remark on the good parts as well.

When something takes longer than expected, write it down

We need more voices in our community. Blogging is great, because there is no gatekeeper to decide who gets to publish and who doesn't. But there is still one hurdle: What to write about?

Pay attention to what you do day to day. If you spent more time figuring out how to do something than you thought you would, it is worth writing down.

Don't worry about looking stupid because others must know how to do it already. You don't have to push the boundaries of human knowledge. That's PhD theses, not blog posts.

Think of it as notes to your future self, a place to put codes and commands in monospace font so you can come back in 3 months to copy and paste them.

Just because some people share more doesn't mean there is no place for you to do it. Everyone has a different experience, and we want to hear from you.

Speak at local meetups

In the original article, the author laments that there is no diversity at conferences. Always the same faces, always the same topics. As a conference organizer, I can tell you that speaker selection is hard. There were so many people that very much deserved a speaking slot but didn't get one, because we had a very limited number. You can read more about how we try to have a balanced speaker roster at 360|AnDev.

That said, we don't have to let conferences be the only place where technical talks are given. There are numerous meetups happening all over the world on any given week. And they are always, always looking for speakers. Sure, it does not come with the prestige of conference speaking, but does that make them worthless?

If you think the local audience is too small to worth your time, record your talk and post it on the internet. I wrote a guide on how to record your screen and voice with QuickTime. Would love it if someone write one for Open Broadcaster Software (OBS)!

Give talks yourself, and encourage those around you to do it. That is how we get new voices. Don't let the conference speaking circuit dictate who gets to speak and who doesn't.

Sharing != Elite Worship

People are lazy. If we see the same name over and over, we think that person must know something. This is fundamentally what leads to elite worship. We can't change human nature, but we can spread the love. Point out each other's good work, encourage each other to make it visible. Make the elite circle so large that it is no longer elite.

Thursday, October 13, 2016

Dennis Ritchie Dies Again

Yesterday many people on my Twitter timeline sharing an article about Dennis Ritchie's death:

I clicked through to read the article, which was from 2011. Why is this circulating again?

My guess is that some people were retweeting without bothering to read the article, and thought he died recently.

This makes me think of a reaction to a tweet I posted.

I was furious. Why would I post something that I'm not sure about? I even backed it up with a slide. Why are you doubting me?

Took me a while to remember that that's what other people do. Say things even when they are only 60% sure. I look back at my career and cringe to think of all the times when other people were regarded more knowledgeable because they open their mouths even when they are not sure.

This time, I am happy that I checked the details before passing it on.

Saturday, October 8, 2016

Constraint Layout: Icon Label Text

I am making one of those classic layouts: an icon with two lines of text. I would like to use vector drawable for the icon, and scale it according to the text sizes. I want the top edge of the icon to line up with the top edge of the first line of text, and the bottom edge of the icon to line up with the bottom edge of the second line.

How would I do that? With ConstraintLayout!

<ImageView
  android:id="@+id/flower_image"
  android:layout_width="0dp"
  android:layout_height="0dp"
  app:layout_constraintTop_toTopOf="@+id/label"
  app:layout_constraintBottom_toBottomOf="@+id/text"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintDimensionRatio="1:1"
  app:srcCompat="@drawable/ic_flower"/>
<TextView
  android:id="@+id/label"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:layout_constraintLeft_toRightOf="@+id/image"
  app:layout_constraintTop_toTopOf="parent"
  android:text="@string/flower"
  android:textSize="16sp"/>
<TextView
  android:id="@+id/text"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:layout_constraintTop_toBottomOf="@+id/label"
  app:layout_constraintLeft_toLeftOf="@+id/label"
  android:text="@string/jasmine"
  android:textSize="24sp"/>

The width and the height of the ImageView is 0dp. This tells ConstraintLayout to compute them by the constraints. In this case, the height of the ImageView is determined by these constraints:

app:layout_constraintTop_toTopOf="@+id/label"
app:layout_constraintBottom_toBottomOf="@+id/text"

The width is the same as the height.

app:layout_constraintDimensionRatio="1:1"

The rest of the constraints are for positioning.

With that, the image scales up as the text sizes increase. It stays sharp because it is a vector.

Layout Editor

I tried to make this layout with the Layout Editor, but could not figure out how to create the constraint app:layout_constraintTop_toTopOf="@+id/label" for the ImageView. I was hovering my cursor around the top edge but not sure how to drag it to link the two views. So I added up playing with the editor a bit to deduce the XML attributes, and switched to editing the XML directly. I hope to use the layout editor in my next attempt to use Constraint Layout.

Follow-up Twitter discussion:

Read the whole Twitter thread.

Source code

github.com/chiuki/iconlabeltext

Click on either TextView to increase its size. Click on the image to reset.

Friday, September 16, 2016

TransactionTooLargeException crashes on Nougat

I was testing my app on Android Nougat, and it crashed when I try to move from one Activity to another. I saw this in the log: java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 700848 bytes.

Actually, the platform has been printing warning log about this for a while, but let's be honest, who has time to read all the logs? Nougat (API 24) throws TransactionTooLargeExceptions as RuntimeExceptions, so we cannot ignore that any more.

onSaveInstanceState

Turns out I was saving a big list of search results during onSaveInstanceState to persist them over rotation. Time to move that to a Loader!

But what is the limit?

But now I'm curious: What is the limit? I wrote a sample app to find out.

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = new Intent(this, AnotherActivity.class);
    startActivity(intent);
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    int length = 1000;
    Uri uri = getIntent().getData();
    if (uri != null) {
      try {
        length = Integer.parseInt(uri.getLastPathSegment());
      } catch (NumberFormatException e) {
      }
    }

    byte[] data = new byte[length];
    outState.putByteArray("data", data);
  }
}

To try different sizes, I start the app like this:

adb shell am start \
  -a android.intent.action.View \
  -n com.sqisland.tutorial.transcation_too_large/.MainActivity \
  -d 700000

This launches MainActivity, which immediately goes to AnotherActivity. When that happens, the system calls onSaveInstanceState, which tries to stash away a byte array of the length specified in the adb command, retrieved by getIntent().getData(). This way, I can try different numbers without recompiling and redeploying the app.

I did a binary search on a Nougat emulator and my Nexus 9. The limit is slightly different, but it hovers around 500000. That is not a small number, but not too hard to exceed if you try to store data rather than state.

Thursday, August 25, 2016

Speaking profile

Your speaking profile showcases your speaking experience. Conference organizers can see where you have spoken at, look at the slides, and watch videos of your talk.

Make one now, even if you are just getting started. You can list the topics you would like to speak about, and then add your talks as you schedule and give them.

Here are 3 places you can host your speaking profile.

Blog page

Most blogging platforms e.g. wordpress, blogger allows you to add pages independent of the blog posts. You can add a speaking page there.

Example: Annyce Davis.

GitHub pages

If you don't have a blog, you can use GitHub pages to host your speaking page.

Example: Margaret Maynard-Reid.

Lanyrd

If you don't want to deal with formatting your page, you can create a profile on lanyrd.com. You will need to find the conference you are speaking at (create it if there is no entry), add a session, and mark yourself as the speaker. It is a bit of a hassle to enter all that structured data, but you get cool stats.

Example: Estelle Weyl.

Further reading

Even more examples: https://github.com/asg-feminati/speakers

Watch my How to Write a Conference Proposal talk where I mentioned how to use speaking profiles to discover conferences.

Friday, August 12, 2016

360|AnDev: Money

360|AnDev is the first time I run a conference. I was raised to be frugal, never spending money that I don't have, but putting on a conference requires exactly that. We have to book the venue, order badges, buy plane tickets for speakers etc, all without knowing if any one will actually buy tickets to the conference. It was nerve-racking.

50 Shades of No

Our first source of income is sponsorship. As a first year conference, we have no track record to show, and it has been difficult to attract sponsors.

We were so grateful that POSSIBLE Mobile and Tack mobile jumped in as sponsors the moment we announced. But after that, we had a long period of nothing. I was cold emailing a lot of companies, getting various versions of no.

  • The classic: No reply.
  • The cliff: Initial interest, but no follow up.
  • The black hole: Ask me to submit to a ticketing system.
  • The clash: "We are already sponsoring a conference in the same city in the same month."
  • The budgeteer: "We have no more budget for this year / month."
  • The freeloader: "We would rather get presence for free through the CFP." (Okay they didn't say that, but that's what happened)

Surprising Yes Stories

I was quite discouraged, to be honest. Fortunately my co-organizer John has put on many conferences before, and knows that everyone procrastinates until the last moment. So I should not give up hope.

And indeed, we got an influx of sponsors in the last month. Some of which are the same people that we have been pinging, and the reminder of "Hey, conference is really soon" kicked them into action.

One sponsor approached us out of nowhere, pretty late. When I talked to them at the conference, they told me that one of their employees saw me at Write/Speak/Code the month before, and the company decided that really want to be a part of our community-focused conference. Wow, I had no idea!

Another sponsor came from counter-solicitation. From time to time I get recruiter emails, and I have been replying with, "No, I don't need a job, but please sponsor my conference to reach out to other Android developers." Most of the time I get "Oh I am just a recruiter I can't make decisions like that", but one company actually followed through and became our sponsor!

I was genuinely surprised. This really reinforces my belief that you should always ask for what you want. You need to give people a chance to say yes!

Attendees

Same as sponsors, attendees are major slackers. I had this exchange with so many of my friends:

Friend: I'm so excited about 360|AnDev!
Me: Yay! You bought your ticket already, right?
Friend: hmm... no.

John told me that they always procrastinate, no matter what you do. I was sitting at the edge of my seat until the day of the conference, not knowing if we were going to break even.

I was promoting the conference as hard as I could, but there was still a lot of people who did not hear about the conference, or did not know until it was too late to arrange travel. Perhaps I have been promoting it within my echo chamber? How can I reach out?

Again?

The conference has come and gone, and yes, we broke even. I went into this knowing that I am not running a conference for the money, but still, the uncertainty was no fun.

Will I run 360|AnDev again next year? Right now I am leaning towards yes. I was so happy to see so many people connecting with each other and lifting each other up. With a stellar first edition, I hope next year it will be easier to get sponsors and sell tickets.

Do you want to be a part of 360|AnDev next year? Sign up to stay in the know!