Pages

10 Jun 2015

Notes on Wearable development


  • Apparently, DataItem is persistent but doesn't work like database. When you send 2 DataItem objects to a same node via same Uri, the second one will replace the first one instead of update field by field. I thought it would work like update statement of database ;(
  • If you send multiple DataItem to wearable while it's out of your handheld's range, the DataApi.DataListener you register on wearable side will only get called ONCE for the last DataItem you sent.

9 Apr 2015

Java Enum's mystery

Today, I accidentally took a look at toMillis(long d) method of Java's TimeUnit class:

https://android.googlesource.com/platform/libcore/+/refs/heads/master/luni/src/main/java/java/util/concurrent/TimeUnit.java

And I was like: "such class, very confusing, much questions, wow" lol

Why this class has toMillis(long d) method, and its enum elements have that method as well?
Why this class's toMillis(long d) has only this line in its implementation?

throw new AbstractMethodError();

It was so confusing because normally I mostly only use enum as cases for switch statements, so I tried to research for a while then I occurred this thread: http://stackoverflow.com/questions/18392885/java-definition-of-methods-and-variables-inside-enums-constant.

Still confusing but somehow I came to this conclusion:
  • Basically we can use Enum as a class to hold constants of a certain type that has certain desired methods OR we can call it "constant method" (I doubt about the latter?!)
  • TimeUnit's toMillis(long d) method basically just throws an exception (AbstractMethodError), and its elements (SECONDS, MINUTES...) have type is TimeUnit, so they just override TimeUnit's toMillis(long d) method (@Override is omitted in this class, I guess the author did it intentionally because he didn't call super method in any overridden methods, and that was the point made this class so confusing at first to me). Then when we call TimeUnit.SECONDS.toMillis(10), SECONDS's toMillis(long d) will be called but it doesn't throw any exceptions because super method wasn't called.
That's it!
The method looks so well-designed but kind of confusing at first.
Now I see it's a really good practice to use Java's Enum.

24 Sept 2014

Show unused resources in Android Studio

Today when I was reading about how to decrease size of an APK file, I discovered a functionality that I have been looking for in Android Studio, it's how to show unused resources. This functionality becomes extremely helpful when you want to optimize your APK file before release, and I believe the smaller your APK file the more download your app will get.

Enough rambling, this is how you get it:
Analyze -> Inspect code...
Then in  Inspection windows (View -> Tool Windows -> Inspection), under Android Lint, you will find an entry named "Unused resources", click on it and you would get something like:



Oh, just one more note, I'm using Android Studio Beta 0.8.11 (Updated from Canary Channel)
Yeah, that's it.

Happy coding ;)

10 Jul 2014

ImageView.setImageBitmap and other ImageView's set image methods

Have you ever stumbled in a case that you use ImageView.setImageResource(R.drawable.your_image) and your image is displayed totally fine in all devices, then you want to make your ImageView more dynamic by put your image into a server, then use something (like Volley, UniversalImageLoader...) to load the image as a Bitmap, then use ImageView.setImageBitmap(your_bitmap) to display your image but it's displayed fine in all devices anymore?!

I got myself into that case today, after using ImageView.setImageBitmap(), my image is displayed too big in some devices and too small in some others. It took me an hour debugging and reading the ImaveView's source code and still couldn't figure out why but reminded me about Android's DisplayMetrics.
As we are developing Android and iOS versions parallel, both share the same resources, and I put all Android's image resources into drawable-xhdpi (as you may know, Android's xhdpi and iOS's retina have the same density), so when I use ImageView.setImageResource(), it displays my images pretty well on all current popular devices (exclude tablets), but why not ImageView.setImageBitmap()?!

The reason is ImageView.setImageResource() cares about device's density, but setImageBitmap() doens't seem to, I think it probably uses some default settings. So to fix it, just use Bitmap.setDensity() with an appropriate density from DensityMetrics. For example, in my case, I would use:

 bitmap.setDensity(DisplayMetrics.DENSITY_XHIGH);


That's it ;-)
Happy coding, guys!

8 Jun 2014

9GAG - TV's iPhone app like animation on Android

I'm always a huge fan of http://9gag.com, and recently, they released a version of http://9gag.tv for iPhone with very cool animation. When I saw it, it aroused my curious, so I tried to implement it on Android, and here is what I've got :)



You can grab the source code here: https://github.com/mrleolink/9GAGTVAnimation

A side note: This is just a simple implementation I have made in a few hours, I tried to reuse views for cards bust just in a very simple way. I believe that this sample can be improved to hook with a custom Adapter to create a completed widget for Android, but I don't have enough of time at the moment, so if any of you have time to implement it, feel free to give me a pull request.

20 May 2014

Android Canvas's clipping functions doensn't work?

I was working on an Android's custom view to show a volume bar with an overlay gradient, it looks somewhat like to this:


My approach was calculate small volume bars's RectF then use Canvas's clipRect to clip the canvas, then draw the gradient and gray part on it. Everything worked well with Nexus 5 and Galaxy S2 LTE, but not with a NTTdocomo Android phone (all of them were 4.0 up).

At first I thought the divider between volume bars was too small but after double checked, it wasn't the reason. Then it took me 2 hours for many checks (Android API Samples) and searches, it's only because of something called Hardware Acceleration, as written in the developer page:

Hardware acceleration is enabled by default if your Target API level is >=14

 So, Hardware Acceleration must be enabled by default on all of my devices, then I tried to turn it off by putting this line into the Activity which contains my custom view:

android:hardwareAccelerated="false"

And it worked!!!

So all the blames should go to the Hardware Acceleration, but why did it still work with Hardware Acceleration ON on two other devices ?!
It's a question that I haven't but need to figure out later!

P/S: The more I work with Android, the more I see this sentence of a random guy on StackOverflow is very true:

Everything is so random with Android!

Hope this help someone out there to not waste 2 hours at work like I did lol, happy coding guys!

UPDATE: I just found this today (20140728) http://developer.android.com/guide/topics/graphics/hardware-accel.html. There is a table about Unsupported Drawing Operations, so you guys can take a look then enable/disable hardware acceleration to match your needs.