tag:blogger.com,1999:blog-62781756910808739712024-03-28T05:24:44.133+01:00Mobile Engineering - thoughts and tips on iOS and Android developmentAdolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-6278175691080873971.post-28159462545640043022014-06-07T23:00:00.001+02:002014-06-07T23:01:41.346+02:00Avoiding Out of Memory errors while loading large bitmapsHi everyone! Has been a long time since I wrote here, and it is time to clean the dust and publish new and hopefully useful stuff :)<br />
Today I will present some suggestion on how to minimize the amount of RAM while loading large bitmap on Android, in order to avoid the common OutOfMemory error.<br />
<br />
New mobile phones and tablets have constantly seen their display to become more capable in term of display resolution. This brings many positive aspects, but for developers, usually a lot of headaches: more capable displays means much more memory required to display images and pictures on them.<br />
<div>
<br /></div>
<div>
An image (a PNG, a JPEG..) is always displayed as a matrix of pixels. Supposing a 32 bit depth color, each pixel is represented as 32 bits, i.e. 4 bytes (R,G,B and alpha component).</div>
<div>
On a modern display (for example, let's take the Nexus 5), we have 1080x1920 pixels. Potentially, an app that shows an image fullscreen (for simplicity we pretend the black bar with status bar and Android system buttons is hidden) must load in memory a bitmap: 4 * 1080 * 1920 = 8294400 bytes big.</div>
<div>
<br /></div>
<div>
This would not be a problem if the only thing loaded in the current instance of dalvik VM is that image, but of course in memory we can have much more objects.</div>
<div>
<br /></div>
<div>
How much memory does Android borrow to a single app? It depends. Each Android device might in theory have a different threshold which dictates how much memory is granted to the application. It is declared as a system property and can be read by typing this on the console:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">adb pull /system/build.prop</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">cat build.prop</span></div>
<div>
<br /></div>
<div>
and checking the property <span style="font-family: Courier New, Courier, monospace;">dalvik.vm.heapgrowthlimit</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> </span></div>
<div>
In general, devices with bigger dpi screens have a higher value of heap limit. For example, the LG Nexus 5, a XXHDPI device, has 192MB of limit. As said, device with the same resolution might have different heap limit: an HTC One X (XHDPI device) has 92MB of limit; a Samsung S3 (also XHDPI) has only 64MB of heap limit.</div>
<div>
<br /></div>
<div>
An app can request more RAM, by declaring the <span style="font-family: Courier New, Courier, monospace;">android:largeHeap</span> property in the Android manifest. How much RAM can be granted? Also this property is defined in the same file (<span style="font-family: Courier New, Courier, monospace;">dalvik.vm.heapsize</span>), and in case of my Nexus 5, is 512 MB.</div>
<div>
Why not just using always this property? Because the GC tends to become inefficient and app will be much slower. </div>
<div>
<br /></div>
<div>
Consequently, in mostly all cases, instead of setting this attribute we need to minimize the amount of RAM needed, especially if we want to tackle the well known OutOfMemory exception.</div>
<div>
<br /></div>
<div>
In order to minimize the possibility of such error, a well-behaving app that need to load a large bitmap must:</div>
<div>
- check the amount of free memory left </div>
<div>
- adopt strategies in case the available memory is not enough to load it.</div>
<div>
<br /></div>
<h4>
</h4>
<h4>
Check the amount of free memory left</h4>
<div>
Android inherits the <span style="font-family: Courier New, Courier, monospace;">Runtime</span> clas sfrom Java standard library. This helps getting the information we fetched via console: in particular, how much memory is available, how much free memory is left before the VM will complain.</div>
<div>
<br /></div>
<script src="https://gist.github.com/nalitzis/5256568eb5d38108b630.js"></script>
In the gist above, I calculate the total available heap (192MB on my device) and the available heap (it was around 175MB before loading the bitmap).
<br />
<br />
<h4>
</h4>
<h4>
Check how big is the bitmap we want to load</h4>
On Android3.0+, we can use a handy class called BitmapFactory.Options. It does a lot of useful things, one of which is giving info about the image, without loading it in memory.<br />
<br />
<script src="https://gist.github.com/nalitzis/d4fdbf768d457ee16ce9.js"></script>
In the snippet above, I use the aforementioned class to calculate image width and height without loading it in RAM, by setting to <span style="font-family: Courier New, Courier, monospace;">true</span> the <span style="font-family: Courier New, Courier, monospace;">inJustDecodeBounds</span> property. We can have a rough aestimate of how large will be the image in RAM from its width, height attributes.<br />
<br />
<h4>
</h4>
<h4>
Load a subscaled version of the bitmap in RAM</h4>
<div>
If the memory available is less than the amount of memory required by the bitmap, then we apply some subsampling. The image will be imperceptibly lower in quality on the specific device where this subsampling will happen, but we will avoid the Out of Memory error. User will be happy and probably won't even notice the difference.</div>
<div>
Again, to subsample the image we use the BitmapFactory.Options:</div>
<div>
<br /></div>
<script src="https://gist.github.com/nalitzis/bad4c1e89a0ec185fb0d.js"></script>
We use power of 2 because the decoder will anyway round other values to a power of 2. Also, I placed a limit o 8 but also this can be avoided and image can be subsampled at any level.<br />
<br />
By subsampling an image with a factor of 2 you can see you will be able to spare almost 75% of memory, and the difference in quality is almost negligible.<br />
<br />
You can download the sample app which contains all these snippets and a demo activity you can play with here: <a href="https://github.com/nalitzis/TestMemoryViews">https://github.com/nalitzis/TestMemoryViews</a>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com57tag:blogger.com,1999:blog-6278175691080873971.post-11430022160296380132013-07-26T22:53:00.001+02:002013-07-27T13:12:47.944+02:00Asynchronous code testing in AndroidTesting asynchronous calls it is not always an easy task.<br />
<br />
Let's take as reference this simple interface:<br />
<br />
<script src="https://gist.github.com/nalitzis/6091726.js"></script>
<br />
The first thing is: how can we test it through an Android unit test class?<br />
<br />
<script src="https://gist.github.com/nalitzis/6091812.js"></script>
<br />
We can't test the value inside the callback. Infact, an async call runs usually in worker thread. When the thread has done some computation, it calls the callback. The simplest case is when the callback is run in the same worker thread.<br />
<br />
But still, we need to find a way to block the main thread, otherwise the test class will simply don't wait before the callback is called! Remember that the method testDoSync() is called in the main thread.<br />
<br />
We can use a semaphore, and make the test method wait until the callback is delivered. Then we can easily test the return value. The Semaphore class has some interesting properties: first, we can use it to put a thread in wait; the acquire() method stops the thread until a resource is available. As we have created the Semaphore with 0 resources available, this will cause the next call to acquire() to stop the thread.<br />
But what if there is the unlikely case that the listener, returns before the acquire() call is made? No worries, as the signal() will simply increment the number of resources available and so the acquire() method will not nlock but will return straight away. Yay, this is for sure a better way to handle threads synchronization that the usual pattern wait-notify!<br />
This is the code that covers this case:<br />
<br />
<script src="https://gist.github.com/nalitzis/6091916.js"></script>
<br />
And now, the worst case. Let's imagine that the code run by the worker thread do some stuff, and then it posts the results of its work in the calling thread (for instance through a handler). Then, onValueChanged() will never be called. Why? It is because we needed to stop the main thread. The main thread is a looper thread: normally a thread do some stuff and then it dies. Instead, a thread with a looper processes events by looping continuously. Another thread can post events on it: the events are put in the thread queue and they are processed one at time. If we block the main thread, the event posted by the worker thread will NEVER get processed.<br />
How to handle this case?<br />
We still need to block the main thread. But we need to launch the callback from a secondary thread with the looper.<br />
We will use a facility offered by android: <a href="http://developer.android.com/reference/android/os/HandlerThread.html">HandlerThread</a>.<br />
<br />
<script src="https://gist.github.com/nalitzis/6092092.js"></script>
It will create a thread with looper for us; then the callback will be called in the secondary thread looper that is not blocked, and from that thread we can release the semaphore of the main thread.<br />
Finally, remember to quit() the thread handler (that will quit the embedded looper too and will cause the death of that thread).<br />
<br />Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com81tag:blogger.com,1999:blog-6278175691080873971.post-79175627685135991532013-07-12T22:37:00.000+02:002013-07-12T22:37:54.669+02:00Dynamic resize of views and offscreen view size calculation in LinearLayoutThe layout is usually handled by a set of xml files, where we specify how the components of our view group are displayed.<br />
It should be the preferred way of generating and composing the views. It is possible to merge layouts, to inflate custom views etc.<br />
There are some occasions, though, where the xml syntax and attributes are not powerful enough.<br />
For example, we can have a vertical linear layout where, at some point, we inflate a custom view. We don't know how big (and, above all), tall is this view at compile time. The problem is, all or some views below it can disappear because our "big" view takes all available space.<br />
<br />
A solution might be to wrap the views in a relative layout. All good, all fine, in that way we can specify that the big view must be <i>below</i> a child, and <i>above</i> another. Then we align the first view to the top, and the last to the bottom.<br />
<br />
But the problem is that the height of the relative layout can't be wrapped!<br />
As stated also in the documentation (which should have read before spending a couple of hours in adapting the layout :P)<br />
<blockquote class="tr_bq">
<span style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px;">Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to </span><code style="background-color: #f9f9f9; color: #006600; font-size: 13px; line-height: 14px;"><a href="http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html#WRAP_CONTENT" style="color: #258aaf; text-decoration: none;">WRAP_CONTENT</a></code><span style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px;"> and a child set to </span><code style="background-color: #f9f9f9; color: #006600; font-size: 13px; line-height: 14px;"><a href="http://developer.android.com/reference/android/widget/RelativeLayout.html#ALIGN_PARENT_BOTTOM" style="color: #258aaf; text-decoration: none;">ALIGN_PARENT_BOTTOM</a></code><span style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px;">.</span></blockquote>
The only way is adjusting the layout at runtime: we must calculate the height of the big view and if its bottom point is at the end of the layout and there are still views to draw, then we need to calculate their value and resize it accordingly.<br />
<br />
A problem is that we can't get simply the height of the offscreen views! Since they are offscreen, Android will give us 0 as the height.<br />
<br />
What we can do, is using the class called <a href="http://developer.android.com/reference/android/view/View.MeasureSpec.html">View.MeasureSpec</a> and calculate the view size like this:<br />
<br />
<script src="https://gist.github.com/nalitzis/5987554.js"></script><br />
<br />
Then, we need to find a way to adjust the size of the big view; again, we can't do that in onCreate() or other similar callbacks, as the view is not rendered yet and we will get 0 as height of the view.<br />
We could override the View.onMeasure() method but as it gets called multiple times by the framework, it is not very reliable.<br />
Best thing is adding a <a href="http://developer.android.com/reference/android/view/ViewTreeObserver.html">ViewTreeObserver</a> and do all the calculations in its callback:<br />
<br />
<script src="https://gist.github.com/nalitzis/5987591.js"></script><br />
<br />
The code of this example is available here:<br />
<a href="https://github.com/nalitzis/TestDynamicViews">https://github.com/nalitzis/TestDynamicViews</a><br />
<br />
<span style="background-color: #f9f9f9; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 19px;"><br /></span>
<br />
<br />Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com2tag:blogger.com,1999:blog-6278175691080873971.post-64168354360412208232013-04-05T22:28:00.000+02:002013-04-05T22:29:46.799+02:00Threads signaling mechanisms in JavaIn Java, there might be situations where you want to perform an operation on a certain thread and then, the same thread should wait for a certain condition before completing its task. This condition happens after another thread completes its execution.<br />
<div>
<br /></div>
<div>
For instance, we want to run a syncronous method on thread-1:</div>
<div>
<br /></div>
<div>
<br /></div>
<script src="https://gist.github.com/nalitzis/5322209.js"></script>
<br />
<div>
<br /></div>
<div>
<br />
A first option to do this is by using the wait() and notify() methods provided by Object class.<br />
The first thread calls wait() and the callback thread calls notify().<br />
<br />
<br />
<script src="https://gist.github.com/nalitzis/5322243.js"></script>
We must be carful though, because if the notify() method happens-before the wait() one, the waiting thread will wait forever.<br />
<br />
To prevent this, we need a boolean variable, that can be used to prevent a similar scenario:<br />
<br />
<br />
<br />
<script src="https://gist.github.com/nalitzis/5322317.js"></script>
</div>
<br />
<br />
It is also possible to use Semaphore class, from java.util.concurrent package and call acquire() and release() methods to do the same thing.<br />
<br />
Take a look also at this interesting tutorial that deals with many important Java concurrency topics:<br />
<a href="http://tutorials.jenkov.com/java-concurrency/index.html">http://tutorials.jenkov.com/java-concurrency/index.html</a>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com9tag:blogger.com,1999:blog-6278175691080873971.post-64444571435881791292013-02-08T23:24:00.001+01:002013-02-08T23:24:24.170+01:00Inter Process Communication on Android: Binders and AidlIn contrast with iOS, where an app can be responsible for only one process at a time, Android provides many ways to create an app which spawns two or many processes. On Android instead, there is the possibility for two different apps (i.e. two different apks) to communicate, or two processes that live in the same apk but in different processes.<br />
In both cases, the system must provide a "channel" that allows two processes to communicate. In contrast with threads, two processes don't share memory for data, therefore the system must provide a way for the data to cross the process boundaries.<br />
<br />
Historically, have been defined many ways to create a communication between two processes (for example, CORBA, or JRMI); Android has defined its own implementation: it is called AIDL, and the acronym stands for Android Interface Definition Language.<br />
<br />
This blog post describe how to create a simple application that spawns two processes, and in detail shows two ways to implement it. The first is through the Messenger class and in many cases it is enough powerful, the second one is more low level, but requires to implement an AIDL interface. In detail, there is a simple Activity that lives in a process (the process where the app lives) and two services. Both the services are remote; the first one communicates with the activity via a Messenger, the second via the AIDL.<br />
<br />
<br />
<script src="https://gist.github.com/nalitzis/4742187.js"></script>
In the code above, there is the important part of the manifest, where the two services are declared. As we can see, to declare a service as remote, we must specify the android:process attribute. The exported attribute tells the system if a component can be exposed to other applications; in case it is true, another app can launch the component. But this is not relevant in our context.<br />
<br />
<br />
<h4>
IPC with Messenger and Handler</h4>
<br />
<div>
This mechanism allows two process to communicate and save the developer from creating AIDL files and it is more simple and straightforward; the system under the hood however will use AIDL but the developer doesn't see it.</div>
<div>
<br /></div>
<script src="https://gist.github.com/nalitzis/4742036.js"></script>
In the code above, it is shown how the service is created and bound.<br />
<br />
<script src="https://gist.github.com/nalitzis/4742111.js"></script>
In the code above, it is shown how the remote service is implemented. If the service is remote, we must implement the method onBind(); the three fundamental components are: binder, messenger and handler.<br />
The service use a handler, used to receive data from a remote process; the binder is as its name suggests, the "thing" that binds the two processes. The messenger is tied to the binder and provides a convenient way for the two sides to communicate effectively. In the example above, the activity generates a Messenger from the binder received as parameter in the onServiceConnected() callback. It will use the messenger to send data to the remote process (method sendMessage()). In the ClientService.java, the handler is used to receive data from the remote process.<br />
<br />
The example shows that the Process ID of the sender is different from the process ID of the receiver and the string sent from the activity is correctly received from the service, that lives in its own process.<br />
<br />
<h4>
IPC with AIDL</h4>
<div>
If we want to use AIDL, we must first specify an interface between the client process and the server one; it is a file with methods shared between the client and the server. These methods are the "entry points" for a process to start the communication with the other process.</div>
<div>
In our case, the scenario is very simple. The aidl file contains only a method (multiply) that multiplies two numbers. The service will take care of the mathematical operation. In the example we don't return a value to the client, but of course it can be done.</div>
<div>
When we define an aidl file, the system will generate the relative implementation in the /gen directory. If you have a look at the implementation, it is easy to spot what happens under the hood: the data which have been serialized before the dispatch, are then received as a Parcelable object, deserialized and then the method at the server side (in this case multiply) is finally called.</div>
<div>
<br /></div>
<div>
<br /></div>
<script src="https://gist.github.com/nalitzis/4742310.js"></script>
<br />
<div>
<br /></div>
<div>
The service implements the Stub (defined as an abstract class in the auto-generated file); the Stub is also the binder (extends Binder).<br />
The activity retrieves the interface to communicate with the server via this method:<br />
<span class="s1">multiplierService</span> = IMultiplier.Stub.asInterface(service);<br />
It returns a client-stub that has the same interface as the counterpart implemented at the server side (AidlService).<br />
When we have the instance, we can banally call the multiply method as if it were a local method:<br />
<br />
<div class="p1">
multiplierService<span class="s1">.multiply(5, 7);</span></div>
<div class="p1">
<span class="s1"><br /></span></div>
<div class="p1">
<span class="s1">The complete code can be found here:</span></div>
<div class="p1">
<span class="s1"><a href="https://github.com/nalitzis/BinderTest">https://github.com/nalitzis/BinderTest</a></span></div>
<div class="p1">
<br /></div>
<div class="p1">
<br /></div>
<div class="p1">
<span class="s1"><br /></span></div>
<div class="p1">
<span class="s1"><br /></span></div>
<br /></div>
Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com8tag:blogger.com,1999:blog-6278175691080873971.post-68114604751501902262012-12-23T22:43:00.002+01:002012-12-23T22:58:26.183+01:00Threading, loopers and messaging queues in AndroidAndroid provides an efficient way to allow communication between different threads.<br />
One thread can communicate with another by creating a <a href="http://developer.android.com/reference/android/os/Message.html">Message</a> object. Usually a Message is not created with the normal constructor; instead, it is used one of the static factory methods provided by the class, for instance <a href="http://developer.android.com/reference/android/os/Message.html#obtain(android.os.Handler, int, java.lang.Object)">obtain(Handler h, int what, Object data)</a>.<br />
<br />
One way to send a message to another thread is to create a <a href="http://developer.android.com/reference/android/os/Messenger.html">Messenger</a> object and invoke the <a href="http://developer.android.com/reference/android/os/Messenger.html#send(android.os.Message)">send</a> method with the Message to send.<br />
But how can we pass to the messenger which thread will receive the message? In the constructor, it is specified the handler bound to the target thread, i.e. the thread that will receive a messenger. An <a href="http://developer.android.com/reference/android/os/Handler.html">Handler</a> is an object that, as its name suggests, when created, binds itself with the thread that is creating it.<br />
Consequently, the receiver thread will create the handler, that will be used by the sender thread that calls the send() method with a Messenger object.<br />
<br />
This is the basic behavior.<br />
But usually we want that, at least the receiver thread, will be running indefinitely, or at least, as long as we need it running.<br />
We can use a <a href="http://developer.android.com/reference/android/os/Looper.html">Looper</a> object to transform a simple "one-shot" thread, in a thread that runs indefinitely, or at least, as long as the quit() method is not called, to quit the loop.<br />
The Looper class "enriches" the behavior of a thread in two ways:<br />
<br />
<ul>
<li>transforms a thread in an indefinite one</li>
<li>creates internally a messaging queue that provides a serialized handling of the messages received. A message received is handled in the <a href="http://developer.android.com/reference/android/os/Handler.Callback.html#handleMessage(android.os.Message)">handleMessage()</a> method of Handler.Callback.</li>
</ul>
<script src="https://gist.github.com/4366268.js"></script>
In the script above, the code between Looper.prepare() and Looper.loop() creates a handler that will handle the messages received by the current thread. If a message is received before the handler has finished processing the message, it will be automatically enqueued and executed as soon as the previous message has been completely processed.<br />
<br />
<script src="https://gist.github.com/4366327.js"></script>
<br />
The Handler subclass manages the incoming message. In the example above, it just prints the data received and sleeps for 2 seconds.
<br /><br />
I have created a short demo project consisting of a main activity and a looper thread. The looper thread processes in its queue messages sent by the main thread (ui thread) of MainActivity. A message is sent each time the button send is pressed by the user. I have inserted a sleep of 2 seconds in the handler() method of the handler bound to the receiver thread, to show that if a user clicks quickly many times on the send button, the message queue handles the incoming messages sequentially, one after the other.<br />
<br />
The demo project can be downloaded from here:<br />
<a href="https://github.com/nalitzis/TestLooper">TestLooper</a><br />
<br />
Pleas note that I had to use wait() and notify() methods because the code that trasforms the thread in a looper is not so immediate, so before getting the handler we must be sure that the looper has been created.
<br />
<ul>
</ul>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com5tag:blogger.com,1999:blog-6278175691080873971.post-72599340834131327002012-10-13T18:34:00.000+02:002012-10-13T18:49:02.022+02:00Remove views with nice animationsIn iOS is very simple to create effective animations on UI components.<br />
<br />
For an app I'm currently working on, I would like to create an animation on a set of views, vertically aligned. When user taps on a button inside the view, the app should start an animation that translates and rotates te view offscreen, while fading it at the same time. At the same time, all the views below it, should react by translating up occupying the space left by the removed view.<br />
<br />
This is the initial scenario:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Z9RCsWMh3kiQBvubyVYgZV559JOma8_QEG3UsCrlOP2Ng77bCguUtzXGtQmBugmoeMl3MbY020Rao_s8yw03UYIwFly1pq_w08WKAiEsqYin2noD2CgzxP6ucU2xSOXiBZjTSugwJ9HR/s1600/Schermata+2012-10-13+alle+18.12.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5Z9RCsWMh3kiQBvubyVYgZV559JOma8_QEG3UsCrlOP2Ng77bCguUtzXGtQmBugmoeMl3MbY020Rao_s8yw03UYIwFly1pq_w08WKAiEsqYin2noD2CgzxP6ucU2xSOXiBZjTSugwJ9HR/s320/Schermata+2012-10-13+alle+18.12.42.png" width="185" /></a></div>
<br />
<br />
To perform this effect, we need two different animations, one on the view to delete, and the other on the views below it.<br />
<br />
This is the first one:<br />
<br />
<br />
<script src="https://gist.github.com/3885194.js?file=gistfile1.m"></script>
To translate all the views below the one that we want delete, we first need to find them:<br />
<br />
<script src="https://gist.github.com/3885208.js?file=gistfile1.m"></script>
<br />
and then we can apply the translation to all of them:<br />
<br />
<script src="https://gist.github.com/3885215.js?file=gistfile1.m"></script>
<br />
The complete sample project can be found here:<br />
<a href="https://github.com/nalitzis/View-delete-animations">https://github.com/nalitzis/View-delete-animations</a>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com5tag:blogger.com,1999:blog-6278175691080873971.post-55200025604284079582012-07-30T17:08:00.001+02:002012-07-30T17:08:38.920+02:00iOS view hierarchySometimes it is usefeul to find the view hierarchy of a certain graphical component.<br />
On iOS, here's a small code snippet to do this:<br />
<br />
<br />
<script src="https://gist.github.com/3207634.js?file=iOS_view_hierarchy.m">
</script>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-87914952169847059602012-07-12T16:30:00.000+02:002012-07-12T16:30:09.521+02:00Android fragments for beginnersFragments have been introduced in Android with the Honeycomb milestone (aka Android 3.0). The main reason was to provide a flexible and powerful solution to deal with different kind of screens (i.e tablets and phone displays).<br />
<br />
An activity layout is composed by one or more viewgroups, at the end, by simple views. Every view group is also called layout. An activity has one root layout, usually set with the <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">setContentView(int resId)</span> call.<br />
<br />
If a layout is composed by many sublayouts/views, having all the UI code and the application logic code for the activity inside one class might quickly increase the complexity and lower the maintainability of the component.<br />
<br />
A solution I've used in the past was to subclass the layout class and create a custom layout where I put all the UI code related to such layout. This approach has a drawback: <span style="background-color: white;">a view group is not an activity. You've to put the app logic code inside the activity and consiquently to provide some sort of communication channel between the view and the activity when, for instance, you want to react to user actions (tap on a button, typing of a text). Components became tightly coupled and difficult to maintain/change.</span><br />
<span style="background-color: white;"><br /></span><br />
<span style="background-color: white;">With Honeycomb (but also in previous releases of the platform, thanks to the compatibility package), you can use <i>fragments</i>. These are like layouts but they have their own lifecycle, they have been created with the aim to contain both UI and app logic code, and can be used to provide an efficient way to deal with layouts that must be placed in different positions depending on the device the app is running on, or on the orientation of the device itself (portrait, landscape).</span><br />
<span style="background-color: white;"><br /></span><br />
<span style="background-color: white;"><br /></span><br />
I've create a simple test project that shows how a layout can be created by different fragments that place themselves in a different way based on the orientation of the device.<br />
<br />
<br />
The activity has provided a main layout for portrait and another for landscape. Fragments are placed in the <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">LinearLayout</span> in a different way depending on the orientation of the device:<br />
<br />
<br />
<script src="https://gist.github.com/3098255.js?file=gistfile1.xml">
</script>
<br />
<script src="https://gist.github.com/3098262.js?file=gistfile1.xml">
</script>
<br />
<br />
The app logic that manages the fragment is inside the fragment itself:<br />
<br />
<br />
<script src="https://gist.github.com/3098276.js?file=gistfile1.java">
</script>
<br />
As you can see, the fragment has framework methods that allow to save the current state. In the sample, a simple counter value is saved and if you change device orientation its valued isn't lost. As you can see, all the application logic pertaining the fragment is inside the fragment. The activity can handle other higher level tasks, such as fragment repositioning/move or orchestrating tasks affecting different portions of the UI.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxZeYXfFLkZR_r3Vox6-D4FsRudTz6Ar2Mw2n_Hxu48fdYIZthiqCBRWcyglSRkX4vSJb7-qm24CucAHoeom9q7keU4CuRh595yUrf1x-09hymT84MuLFcF6MXPF-J4qlnxQEYNlulZEB9/s1600/device-2012-07-12-162223.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxZeYXfFLkZR_r3Vox6-D4FsRudTz6Ar2Mw2n_Hxu48fdYIZthiqCBRWcyglSRkX4vSJb7-qm24CucAHoeom9q7keU4CuRh595yUrf1x-09hymT84MuLFcF6MXPF-J4qlnxQEYNlulZEB9/s320/device-2012-07-12-162223.png" width="192" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCeUAYHmarjILrUlHAEqvNa-K-4uLiIGWy2dg8OQdZagYbNt053wQvttleUwCcBf7QpPPYQGMMD7RQWGsCWBSGVPEwvCPlmhR8y4MKXFVd8EJH4fMXaKh8923k3iljkAwiMOKEf_SM-sCK/s1600/device-2012-07-12-162243.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCeUAYHmarjILrUlHAEqvNa-K-4uLiIGWy2dg8OQdZagYbNt053wQvttleUwCcBf7QpPPYQGMMD7RQWGsCWBSGVPEwvCPlmhR8y4MKXFVd8EJH4fMXaKh8923k3iljkAwiMOKEf_SM-sCK/s320/device-2012-07-12-162243.png" width="320" /></a></div>
<br />
<br />
The sample code can be found here:<br />
<br />
<a href="https://github.com/nalitzis/SampleFragments">https://github.com/nalitzis/SampleFragments</a><br />
<br />Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com1tag:blogger.com,1999:blog-6278175691080873971.post-87455018196844657882012-06-02T12:11:00.000+02:002013-02-13T23:10:24.228+01:00Audio mix and record in AndroidiOS offers, among its frameworks, many interesting features that allow to create audio tracks by simply mixing multiple tracks together. You can use Audio Unit and its methods, as described here:<br />
<br />
<a href="http://developer.apple.com/library/ios/#documentation/AudioUnit/Reference/AUComponentServicesReference/Reference/reference.html#//apple_ref/doc/uid/TP40007291">http://developer.apple.com/library/ios/#documentation/AudioUnit/Reference/AUComponentServicesReference/Reference/reference.html#//apple_ref/doc/uid/TP40007291</a><br />
<br />
But what if you need a similar result on Android? Android does't offer such feature in its audio framework. So I've spent a couple of days on google groups and stackoverflow, reading unanswered questions of android devs searching for a similar functionality on the Google mobile platform, or developed and released by third party contributors and external devs.<br />
It appears there isn't nothing available.<br />
So I've studied the problem and the tools I had to solve it. First let's see what possibilities the platform offers to play files.<br />
Android audio framework consists of these main classes for audio playback:<br />
<br />
<br />
<ul>
<li>MediaPlayer: useful to play compressed sources (m4a, mp3...) and uncompressed but formatted ones (wav). Can't play multiple sounds at the same time. [HIGH LEVEL methods]</li>
<li>SoundPool: can be used to play many raw sounds at the same time.</li>
<li>AudioTrack: can be used as SoundPool (raw sounds), but need to use threads to play many sounds at the same time. [LOW LEVEL methods]</li>
</ul>
I've found that AudioTrack works fine to play uncompressed raw data, and if you want to play multiple sounds at the same time, you can create different threads and start the playback in an asynchronous fashion.<br />
Unluckily this is not always precise: sometimes you can experience a delay before a certain sound is played, and in such cases the final result is far from acceptable.<br />
<br />
Another option is to mix sounds <i>before</i> playing them. This option offers you a nice plus: you obtain the mixed sound that is ready to be stored on file. If you mix sounds with SoundPool for instance, then when you play it, you cannot grab the output and redirect it to a file descriptor instead of to the audio hardware (headphones or speaker).<br />
As mentioned at the beginning, there is no ready solution for such problem. But actually we will see the solution is rather trivial.<br />
<br />
Before delving in the details of how 2 sounds can be mixed together, let's see how can we record a sound on Android. The main classes are:<br />
<br />
<br />
<ul>
<li>MediaRecorder: sister-class of MediaPlayer, can be used to record audio using different codecs (amr, aac). [HIGH LEVEL methods]</li>
<li>AudioRecord: sister class of AudioTrack. It records audio in PCM (Pulse Code Modulation) format. It is the uncompressed digital audio format used in CD Audio, and it is very similar to .wav file format (the .wav file has 44 bytes header before the payload). [LOW LEVEL methods].</li>
</ul>
<br />
<br />
AudioRecord offers all the features we want be able to control: we can specify the frequency, the number of channels (mono or stereo), the number of bit per sample (8 or 16).<br />
<br />
<br />
<script src="https://gist.github.com/2857519.js?file=gistfile1.java">
</script>
In the fragment of code posted above, there is a simple function that can be used to record a 44.1khz mono 16 bit PCM file on the external storage. The function is blocking so it must be run on a secondary thread; it continues to record until the boolean isRecording is set to false (for example when a timeout expires or when a user taps on a button).<br />
<br />
And now comes the most interesting part: how to mix two sounds together?<br />
<br />
Two digital sounds can be mixed easily if files have the same features (same number of channels, same bit per samples, same frequency). This is the simplest scenario and is the only one I'm covering in this post.<br />
Every sample in such case is a 16 bit number. In java a short can be used to represent 16 bit numbers, and infact AudioRecord and AudioTrack work with array of shorts, which simply constitute the samples of our sound.<br />
<br />
This is the main function used to mix 3 sounds together:<br />
<br />
<br />
<script src="https://gist.github.com/2857551.js?file=gistfile1.java">
</script>
There are some complementary methods I'm not posting here because this post is already too long :) but these are some small hints of what they do:<br />
<br />
<ul>
<li><i>createMusicArray</i> reads the stream and returns a list of short objects (the samples)</li>
<li><i>completeStreams</i> normalizes the streams by adding a series of '0' shorts at the end of smaller files. At the end the 3 files have all the same length.</li>
<li><i>buildShortArray</i> converts the list in an array of short numbers</li>
<li><i>saveToFile </i>saves to file :)</li>
</ul>
The key point in the method is that we sum every sample together. We normalize the short to a float [-1,1] so we dont have under/overflow issues. At the end we reduce a bit the volume and we save it in the new array. That's it!<br />
<br />
Of course this is the simplest scenario; if the samples have different frequency we should do other computations. But I think most of the time we want to mix sounds we can also control how they are recorded thus reducing its complexity a lot.<br />
<br />
Once we have a PCM mixed sound, it can be transformed in a .wav file so that every player can read it.
EDIT: as many people have asked me some more help, below it is the code snippet to build a short array from a file containing a raw stream.
<script src="https://gist.github.com/nalitzis/4948802.js"></script>
Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com54tag:blogger.com,1999:blog-6278175691080873971.post-56840527564116407752012-05-12T17:45:00.000+02:002012-05-12T18:14:53.626+02:00TDD - Testing AsyncTasks on AndroidTesting functionalities of a software system is probably one of the most important things to do if you want to release a reliable application to your clients.<br />
<br />
TDD (aka Test Driven Development) is a methodology where you create and develop unit tests before writing a single line of application logic. This strategy allows you to better understand the problem your app is solving, it gives you a more pragmatic and structured way to build a software component. It forces you to design and think to the solution in detail before coding it. And, most important, when you change something in your code, you can safely run your tests again and have an immediate result if your changes have affected the behavior of the component.<br />
<br />
I usually do TDD to test model classes, database classes and networking. I'm not writing functional tests on the UI but Android offers you tools like <a href="http://developer.android.com/guide/developing/tools/monkey.html">monkey</a> to test also user clicks on your UI.<br />
<br />
If your code use AysncTasks to perform networking operations in a background thread, things become a little trickier.<br />
<br />
Normally, in a <a href="http://developer.android.com/reference/android/os/AsyncTask.html">AysncTask</a>, you can specify a result of this task using <a href="http://developer.android.com/reference/android/os/AsyncTask.html#onPostExecute(Result)">onPostExecute</a>.<br />
<div>
This call is executed on the main thread so you can update your UI and notify the user easily.</div>
<div>
<br /></div>
<div>
AsyncTask runs your task in a background thread, but this opens some issues: our tests must be run on the main thread! We need to wait for the AsyncTask to finish before jumping to the next test or to quit the testing routine.</div>
<div>
There is a method called <b><a href="http://developer.android.com/reference/android/test/InstrumentationTestCase.html#runTestOnUiThread(java.lang.Runnable)">runTestOnUiThread</a> </b>that perform a testcase on a main thread. To use such method, your class must extend InstrumentationTestCase.</div>
<br />
<script src="https://gist.github.com/2667258.js?file=gistfile1.java">
</script>
<br />
<div>
<br />
<pre style="background-color: white; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left;"></pre>
</div>
<div>
<br /></div>
In the previous code snippet, I'm creating a unit test called testGetMedia whose purpose is doing some networking in an asynchronous fashion, to fetch some data from a remote backend.<br />
The tested class is called NetworkTasks and it contains a method called getMedia(Media) similar to this one:<br />
<br />
<script src="https://gist.github.com/2667275.js?file=gistfile1.java">
</script>
<br />
<br />
GetAsyncMediaTask is a subclass of AsyncTask that implements the doInBackground() and the onPostExecute() methods. I'm not showing the code of GetAsyncMediaTask here because is not really interesting for our purpose. In the doInBackground() method an http call is placed and it blocks the calling thread until it gets an HttpResponse; inside the onPostExecute() method, I'm using the listener passed to the NetworkTasks object to notify the component that has launched it. The component is notified through onFail and onSuccess callbacks.<br />
In the code snippet the listener is called GetMediaListener.<br />
This covers almost everything except for few (important!) details: what happens in the GetMediaListener?<br />
<script src="https://gist.github.com/2667280.js?file=gistfile1.java">
</script>
<br />
<pre style="background-color: white; font-family: 'Bitstream Vera Sans Mono', Courier, monospace; font: normal normal normal 12px/normal Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; line-height: 1.4em; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left;"></pre>
<br />
<br />
The GetMediaListener extends a generic CallbackListener which in turn implements a simple interface with two methods (onFail and onSuccess).<br />
The callbacks are here used to assert that a condition holds or doesn't hold. The listener used in the real code will do some useful stuff on the UI, trigger some notifications and so on.<br />
And here comes into play the <a href="http://developer.android.com/reference/java/util/concurrent/CountDownLatch.html">CountDownLatch</a> object. It is absolutely mandatory to use this object when you want to test an AsyncTask. Infact, even if we're running the task on the main thread, as soon as the doInBackground method ends, the testGetMedia() method ends too, and there is no way for the listener to be invoked by the system! By using a CountDownLatch, we impose the current thread to stop and wait until a certain condition is met: here we wait that the callback onPostExecute (which in turns call onFail or onSuccess) is executed: as soon as it is executed, the object is decremented with the countdown() method of the supreclass and the lock is removed. The lock is automatically removed after 30 seconds by the signal.await() call.<br />
<br />
You can get all the code here: <a href="https://gist.github.com/2667108">https://gist.github.com/2667108</a><br />
<br />
Enjoy async TDD on Android! :)Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com131tag:blogger.com,1999:blog-6278175691080873971.post-6110902082039055932012-04-04T19:13:00.002+02:002012-04-04T19:21:09.768+02:00Android: screen densities and sizes. How to calculate themFor me it has always be complex to find out, for each android device, what is its density and its screen size. I'll try to explain in this article what i've discovered so far.<br />
It is really very important to find out these 2 parameters, since Android has a way to distinguish which resources to use (both xml layout files and drawables) based on such parameters.<br />
<br />
In detail, Android allows you to specify your drawable resources based on the screen density of your phone. The 4 screen densities available are:<br />
<br />
<br />
<ul>
<li>ldpi - 120 dpi</li>
<li>mdpi - 160 dpi</li>
<li>hdpi - 240dpi</li>
<li>xhdpi - 320 dpi</li>
</ul>
Each specifies a different screen density, i.e. a different amount of pixels for square inch of screen. These are called dpi or dots per inch.<br />
<br />
For example, a HTC Desire has a density of 240dpi, i.e there are 240 pixels for each square inch of screen.<br />
A LG Optimus One has a density of 160dpi, i.e. there are 160 pixels for each square inch of screen. Obviously, if we provide the same icon on these devices, it will show itself larger or the LG than on the HTC phone. A way to cope with that is to specify a layout that uses density independent pixels. But that's another story.<br />
<br />
Let's focus on the dpi. How can we calculate this value? Let's take the two parameters that we always know of a device: diagonal in inches and screen size in pixels.<br />
The HTC Desire has: 800 x 480 and 3.7''.<br />
dpi = sqrt(w^2 + h^2)/d = sqrt(800^2 + 480^2)/3.7 = 252,1<br />
<br />
So the screen density of HTC Desire is HDPI.<br />
<br />
the display size is important because usually we associate different layouts to different screen sizes. A device can have 4 screen sizes:<br />
<br />
<ul>
<li>small-screen</li>
<li>normal-screen</li>
<li>large-screen</li>
<li>xlarge-screen</li>
</ul>
On the Android dev <a href="http://developer.android.com/guide/practices/screens_support.html#range">website</a>, they tell us that a medium screen is more or less between 3 and 5''. But is there a scientific way to calculate it?<br />
They also tell us that:<br />
<br />
<br />
<ul>
<li>small-screens must have a screen size of 426 x 320 dp = 136320 dp</li>
<li>normal-screens must have a screen size of 470 x 320 dp = 150400 dp</li>
<li>large-screens must have a screen size of 640 x 480 dp = 326400 dp</li>
<li>xlarge-screens must have a screen size of 960 x 720 dp = 691200 dp</li>
</ul>
<div>
Usually phones are in the small and normal category, while tablets are in the large and xlarge category, although there are some important exceptions to this rule.</div>
<br />
<br />
<br />
How to calculate the display size for a device? Let's take the HTC Desire as example.<br />
The HTC Desire has: 800 x 480 and 3.7'' and is a HDPI device with a scale of 1,57, so each virtual pixel counts as 1.57 physical pixels. This is known as scale and can be determined as: 252/160. A device with 160 dpi has a scale of 1 (1 physical pixel counts a s1 virtual pixel). This was the density of the first Android phone.<br />
<br />
So: 800/1,57 = 510 dp; 480/1,57 = 305 dp<br />
520 * 305 = 155550 dp which is higher than 150400 but lower than 326400. So the HTC Desire has a normal screen.<br />
<br />
A particular case is give by the recent Galaxy Note. This device has: 1280x800 5.3'' display.<br />
So the DPI is 284,8. Its scale ratio is 1.77. It is between 1.5 and 2. Aaagh.. So in what screen density folder should we put the drawables? A search on stackoverflow suggest that the Note si considered as XHDPI screen.<br />
But here's the problem. We said that phones have a small or medium size screen. This is WRONG for the Galaxy Note.<br />
Infact: 1280/1,77 = 724 dp; 800/1,77 = 451<br />
724 * 451 = 326524 which is larger than 326400<br />
<br />
So if you want to filter your app based on the screen size, be careful. Some phones, like the Galaxy Note, belongs to the Large screens device family!<br />
<br />
<br />
<div>
<br /></div>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com7tag:blogger.com,1999:blog-6278175691080873971.post-81029109216795586602012-03-12T22:20:00.000+01:002012-03-13T10:06:17.531+01:00Tables and cell selections: iOS UITableView vs Android ListView<br />
<br />
One of the first things every dev learns when he/she starts developing on a mobile platform is how to present sets of data. They could be a list of shops, an array of products and so on.<br />
Both Android and iOS have a component to manage this kind of data: <a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a> for the former, and <a href="https://developer.apple.com/library/ios/#documentation/uikit/reference/UITableView_Class/Reference/Reference.html">UITableView</a> for the latter.<br />
<br />
These classes surprisingly offer a similar interface, and have similar ways to provide the datasource to it.<br />
<br />
Both platforms have a component to show the elements on screen and a datasource (or adapter) that manages the presentation of the tableview cells, the cells reuse and how data are presented (in which order).<br />
<br />
iOS has a protocol, <a href="https://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html">UITableViewDataSource</a>, that every class that wants to provide some data to a UITableView must implement. The key method used to provide the tableView cells is<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><span style="background-color: white;">- (UITableViewCell *)tableView:(UITableView *)</span><em style="background-color: white;">tableView</em><span style="background-color: white;"> cellForRowAtIndexPath:(NSIndexPath *)</span><em style="background-color: white;">indexPath</em></span><br />
<br />
<span style="font-family: inherit;">On the other side, Android datatsource is a class that extends <a href="http://developer.android.com/reference/android/widget/ListAdapter.html">ListAdapter</a>.</span><br />
Also this class has a method that must be always implemented:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s1">public</span> View getView (<span class="s1">int</span> position, View convertView, ViewGroup parent) </span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span style="font-family: inherit;">In both platforms it is very important to reuse the cells: with iOS 5 the cell recycle is managed by the system, in case the cell is declared in the .xib file as the default subview of the UITableView. It is very important though to specify a cell-id in code that matches the one declared in the .xib file.</span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: inherit;">Android use a system quite similar to that used by iOS 4.x and lower. You fetch a view inflating it from an xml file only if the view provided by the framework is null (i.e. there isn't currently a reusable cell).</span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: inherit;">This is a typical iOS 5.0 implementation:</span><br />
<span style="font-family: inherit;"><br /></span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellId"];</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> cell.textLabel.text = [_list objectAtIndex:indexPath.row];</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> cell.selectionStyle = UITableViewCellSelectionStyleGray;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> return cell;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span style="font-family: inherit;">While this one is an Android implementation of getView():</span><br />
<span style="font-family: inherit;"><br /></span><br />
<br />
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s1">public</span> View getView (<span class="s1">int</span> position, View convertView, ViewGroup parent){</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>LinearLayout layout;</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span style="background-color: yellow;"><span class="s1">if</span>(convertView == <span class="s1">null</span>){</span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>LayoutInflater inflater = (LayoutInflater)<span class="s2">context</span>.getSystemService(<span class="s2">LAYOUT_INFLATER_SERVICE</span>);</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>layout = (LinearLayout)inflater.inflate(R.layout.<span class="s2">cell</span>, <span class="s1">null</span>);</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>}</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s1">else</span>{</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>layout = (LinearLayout)convertView;</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>}</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span>((TextView)layout.findViewById(R.id.<span class="s2">cell_title</span>)).setText(<span class="s2">dataSource</span>.get(position));</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="s1">return</span> layout;</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span"></span>}</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p1">
The highlithed row shows the comparision made to establish if a convertView is available. If not, it is inflated from the XML layout file.</div>
<div class="p1">
<br /></div>
<div class="p1">
Another important issue to face is how to customize the list selector.</div>
<div class="p1">
In iOS it is a very straightforward procedure: just specify the selection style, or if you want a different color, create a background view with the color you want as its background and assign it to the <span style="font-family: 'Courier New', Courier, monospace;">selectedBackgroundView</span> property (see: <a href="http://stackoverflow.com/questions/1998775/uitableview-cell-selected-color">http://stackoverflow.com/questions/1998775/uitableview-cell-selected-color</a>).</div>
<div class="p1">
<br /></div>
<div class="p1">
On Android, a premise is necessary. Every component (button, tetview, and also cell views) has different states that define how the rendering engine should show them on screen. The states are: pressed, focused, selected, enabled.</div>
<div class="p1">
Concerning the ListView component, the system provides a way to select cells that is specified by a property called listSelector. The listSelector is an xml file with a set of rules, similar to the rules you specify on a css web page, that define how an item is shown in a set of possible states.</div>
<div class="p1">
I've found very difficult to customize this behavior. Every time I tried to customize the cell selection appeareance, I came across many different issues: some times the selection changed the appeareance of all the tableview items, some other times the cell divider disappeared from screen.</div>
<div class="p1">
<br /></div>
<div class="p1">
In the official samples app there isn't a single example on how to customize such property, and also watching the World of ListView Google IO Session didn't helped me a lot (see link here : <a href="http://www.youtube.com/watch?v=wDBM6wVEO70">http://www.youtube.com/watch?v=wDBM6wVEO70</a> )</div>
<div class="p1">
<br /></div>
<div class="p1">
So I came up with a simple yet effective solution: get rid of the listSelector property by imposing a transparent view for every possible state, and by modifying the background of the cell items instead.</div>
<div class="p1">
<br /></div>
<div class="p1">
This is the selector I've used:</div>
<div class="p1">
<br /></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s1"><?</span><span class="s2">xml</span><span class="s3"> </span>version<span class="s3">=</span><span class="s4">"1.0"</span><span class="s3"> </span>encoding<span class="s3">=</span><span class="s4">"utf-8"</span><span class="s1">?></span></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s1"><</span><span class="s2">selector</span><span class="s3"> </span><span class="s5">xmlns:android</span><span class="s3">=</span>"http://schemas.android.com/apk/res/android"<span class="s3"> </span><span class="s1">></span></span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace;"><!-- <item android:drawable="<span class="s6">@color</span>/test_color" android:state_pressed="true" android:state_selected="true"></item> --></span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace;"><!-- <item android:drawable="<span class="s6">@color</span>/test_color" android:state_pressed="false" android:state_selected="true"></item> --></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s3"> </span><span class="s1"><</span><span class="s2">item</span><span class="s3"> </span>android:drawable<span class="s3">=</span><span class="s4">"@color/test_color"</span><span class="s3"> </span>android:state_pressed<span class="s3">=</span><span class="s4">"true"</span><span class="s3"> </span>android:state_selected<span class="s3">=</span><span class="s4">"false"</span><span class="s1">></</span><span class="s2">item</span><span class="s1">></span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s3"> </span><span class="s1"><</span><span class="s2">item</span><span class="s3"> </span>android:drawable<span class="s3">=</span><span class="s4">"@color/black"</span><span class="s3"> </span>android:state_pressed<span class="s3">=</span><span class="s4">"false"</span><span class="s3"> </span>android:state_selected<span class="s3">=</span><span class="s4">"false"</span><span class="s1">></</span><span class="s2">item</span><span class="s1">></span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace;"><span class="s1"></</span>selector<span class="s1">></span> </span></div>
<div class="p1">
<br /></div>
<div class="p1">
You can also uncomment the first two rows if you want to manage the selected state (it is useful if your device has a D-Pad).</div>
<div class="p1">
<br /></div>
<div class="p1">
the source code is available at github.<br />
iOS: <a href="https://github.com/nalitzis/tableview-iphone">https://github.com/nalitzis/tableview-iphone</a><br />
android: <a href="https://github.com/nalitzis/tableview-android">https://github.com/nalitzis/tableview-android</a><br />
<br />
<br /></div>
<div class="p1">
<br /></div>
<br />
<br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: inherit;"><br /></span>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com6tag:blogger.com,1999:blog-6278175691080873971.post-24874701571964163482012-03-04T10:47:00.000+01:002012-03-04T10:47:51.614+01:00Eclipse: Java compiler complianceIf you want to avoid build errors on the @Override annotation, you must change the Java compiler compliance.<br />
<br />
The steps to do so:<br />
<br />
Preferences -> Java -> Compiler -> JDK Compliance<br />
<br />
and set it to 1.6Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-3606351729949888592012-03-04T10:44:00.004+01:002012-03-04T10:48:12.948+01:00Eclipse and Android: projects build orderWhen you work on a project it may happen that at a certain point you include other projects in your workspace and you want to include them as dependencies.<br />
<br />
The build order is very important and you have to specify it correctly otherwise the Eclipse IDE will generate compile errors almost every time the project is re-built (i.e every time you open Eclipse or you get the latest version from a repo).<br />
<br />
To customize the build order in Eclipse:<br />
<br />
General -> Workspace -> Build OrderAdolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com2tag:blogger.com,1999:blog-6278175691080873971.post-88290093504853503102012-02-25T17:36:00.000+01:002012-02-25T17:43:19.261+01:00NFC, Android, accelerometer and Node.JS can transform your mobile in a brush!Last saturday I went to Bologna with two colleagues (<a href="https://twitter.com/#!/robb_casanova">@robb_casanova</a> as frontend artisan/dev and <a href="https://twitter.com/#!/emmegiii">@emme_giii</a> as mobile UX guru), and together we participated in a contest called HackReality. <a href="http://www.whymca.org/evento/whymca-hack-reality-bologna-04-02-2012">http://www.whymca.org/evento/whymca-hack-reality-bologna-04-02-2012</a><br />
<br />
Our intent was to mix up some native and web based technologies to transform a mobile phone into a brush, and a wall into a virtual canvas where a user, with its Android phone, could draw multi colored traits.<br />
<br />
We used some NFC tags sticked on a paper-made palette:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32h5LfQ3eeI1RQEvtFCQIvHjA7Hgm-Sy1HfUU9xQfxZ3xNfFNCLqdpFWUI0FCy7F6VmNoyyOSWk5624XTQAziMhXY2T_GAQ_77reTF3Qlf2fywPOvVYU6fGzsPF1zrQmiBfy1z9WzWJuQ/s1600/pic1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32h5LfQ3eeI1RQEvtFCQIvHjA7Hgm-Sy1HfUU9xQfxZ3xNfFNCLqdpFWUI0FCy7F6VmNoyyOSWk5624XTQAziMhXY2T_GAQ_77reTF3Qlf2fywPOvVYU6fGzsPF1zrQmiBfy1z9WzWJuQ/s320/pic1.jpg" width="320" /></a></div>
<br />
<br />
We used my Galaxy Nexus as a "brush": by tapping the phone on a NFC tag on the palette we changed the paint color. Then we used the accelerometer data to detect accelerations on X and Y axis.<br />
Data were sent to a server running socket.io on top of Node.js. We finally implemented a canvas and we used Processing language to perform the actual drawing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiltvvzP5lJwHYlthqTB0r0G6CbpVl480MoYs423p-blZzsetHRwWiuG_2_bwmybsvc78egs33BKgSJ_b2n985ocLdYLNPLfeNMJAVpSELJG4YwZBPt2njfZvdaMxoGh-5Er8Jc8T1570gX/s1600/pic2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiltvvzP5lJwHYlthqTB0r0G6CbpVl480MoYs423p-blZzsetHRwWiuG_2_bwmybsvc78egs33BKgSJ_b2n985ocLdYLNPLfeNMJAVpSELJG4YwZBPt2njfZvdaMxoGh-5Er8Jc8T1570gX/s320/pic2.png" width="320" /></a></div>
<br />
<br />
The source code for the client-side part of project is available at github: <a href="https://github.com/nalitzis/hackday_client">https://github.com/nalitzis/hackday_client</a><br />
<br />
If I'll have time, in next posts I will explain how the NFC part works.<br />
<br />Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com4tag:blogger.com,1999:blog-6278175691080873971.post-10468485197591210852011-12-28T18:43:00.001+01:002011-12-28T18:43:27.882+01:00Debug with Galaxy Nexus on Windows7In case your adb doesn't show your new shiny Galaxy Nexus, it is probably because your OS doesn't have the required USB driver already installed.<br />
On MacOSX everything went fine from the beginning, but on Windows 7 I couldn't manage to make it appear under the devices window (in DDMS perspective).<br />
<br />
Then I found this thread on stackoverflow:<br />
<br />
<a href="http://stackoverflow.com/questions/8371787/eclipse-doesnt-show-my-galaxy-nexus-with-android-4">http://stackoverflow.com/questions/8371787/eclipse-doesnt-show-my-galaxy-nexus-with-android-4</a>
<br />
<br />
Just install the 26MB driver (eek!) and everything should work fine.Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com7tag:blogger.com,1999:blog-6278175691080873971.post-57287315960274625082011-12-25T17:58:00.000+01:002012-01-14T19:23:36.181+01:00How to use Bitbucket to remotely control your git projects<br />
<a href="https://bitbucket.org/">Bitbucket </a>is an interesting service that allows to remotely store git and mercurial projects. It is reliable, easy to configure and free. Most important, you can have as many private repositories as you want.<br />
<br />
In this post I'll explain how to commit and init a remote git repository on bitbucket starting from a local git repository. This is what I usually do in my projects: I start them locally, then commit locally via git and finally backup a remote copy via bitbucket.<br />
<br />
These are the steps necessary to do that:<br />
<ul>
<li>create a remote empty git repository on your account at bitbucket.org</li>
<li>if you haven't already a local git repo, initialize your project locally by typing <span style="font-family: 'Courier New', Courier, monospace;">git init </span></li>
<li><span style="font-family: inherit;">copy your standard .gitignore file in the project root directory</span></li>
<li><span style="font-family: inherit;">commit locally (using the commit command or with a GUI tool like gitx, gitc, or gitk)</span></li>
</ul>
At this point you're ready to commit remotely. First of all your local git environment must be setup to point to the remote repository:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">git remote add origin https://<username>@bitbucket.org/<username>/sampleproject.git</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: inherit;">Here I assume that your project is named sampleproject; you must substitute the <username> key with your bitbucket account name.</span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: inherit;">If everything goes fine, you're ready to do your first push on your bitbucket repo:</span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">git push -u origin master</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: inherit;">To fetch the remote project from another machine just type:</span><br />
<span style="font-family: inherit;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;">git clone </span><span style="font-family: 'Courier New', Courier, monospace;">https://<username>@bitbucket.org/<username>/sampleproject.git</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-1891168744171534402011-12-24T16:27:00.004+01:002011-12-25T16:05:13.387+01:001 week with the Samsung Galaxy Nexus - first impressionsToday is one week since I've bought the first Android phone shipped with Ice Cream Sandwich, the new <a href="http://developer.android.com/sdk/android-4.0-highlights.html">major OS update</a> that has the ambition to unify the UI and the OS of Android smartphones and tablets.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://p.twimg.com/Ag3Gng0CQAAmn25.jpg:large" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://p.twimg.com/Ag3Gng0CQAAmn25.jpg:large" width="382" /></a></div>
<br />
<br />
<br />
The reasons that induced me to buy the <a href="http://www.google.it/nexus/">Galaxy Nexus</a> where many but the main were:<br />
<br />
<ul>
<li>a brand new OS (new major Linux kernel, competely new UI)</li>
<li>some unique hardware features (720x1280 pixel screen), new sensors (NFC, barometer)</li>
</ul>
For a developer like me this new HW/SW configuration represents new challenges and potential opportunities and I wanted to be involved in such things as soon as possible.<br />
<br />
Today I want to share my impressions as user, but in the following weeks I'll try to post some more tecnhical stuff as well.<br />
The first thing I've noticed when I've switched on the phone is the new UI. It is really well made, very smooth. They have done a great job graphically. The screen is huge (4.65''), but the phone fits well in my jeans pockets, since it is also very slim (I think is 8mm thick) and the surface is a bit curved.<br />
The things I like more are the special effects on photos and videos (expecially the runtime effects that can be applied to mouth, nose and eyes). But I'm sure the "wow effect" feature is without any doubt the face unlock feature. It is simply astonishing. Every time I face unlock my phone, I think "how can this be possible" and actually forget why I wanted to unlock it.<br />
The battery life has also been improved: I often have 50% of power left when I switch it off at night, after a normal daily usage.<br />
Another great thing is that starting with Android 4.0, apps can be fully installed on the SD card, and this is a fundamental improvement that will allow to download hundreds of apps. This was a feature that was lacking in Android 2.x and maybe it is the main complaint I have to move against the previous version of the OS.<br />
Lets' talk about the negative things I've noticed so far: first of all, it is a development phone; you get the updates quickly, but often the release is not as stable as one may hope for. Last week I had to manually reboot the phone a couple of times. The 4.0.1 release has a bug that prevents me to work with blank NFC tags, because the phone expects to work with already NDEF-formatted tags. I hope in a fix in the near future. Another downside I have noticed is that simetimes the UI becomes a bit sluggish. Many discussions have been made on this topic (see this interesting post by <a href="https://plus.google.com/u/0/100838276097451809262">Andrew Munn</a> <a href="https://plus.google.com/u/0/100838276097451809262/posts/VDkV9XaJRGS">https://plus.google.com/u/0/100838276097451809262/posts/VDkV9XaJRGS</a> and the reply made by Android guru <a href="https://plus.google.com/u/0/105051985738280261832">Dianne Hackborn </a><a href="https://plus.google.com/u/0/105051985738280261832/posts/XAZ4CeVP6DC">https://plus.google.com/u/0/105051985738280261832/posts/XAZ4CeVP6DC</a> ) but i think the main culprit here might be the super huge display: the Galaxy Nexus shares the same HW configuration of the SGS 2, but it has twice the pixels of such phone. Plus, Android 4 has introduced some very nice animations (e.g when you switch between the home screen and the apps/widget screen) that might introduce some lags.<br />
In conclusion, this is certianly a great phone, probably the best and most technologically advanced smartphone you can get today.<br />
<br />
<br />Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com1tag:blogger.com,1999:blog-6278175691080873971.post-48450529808096011662011-12-14T17:12:00.000+01:002011-12-14T17:12:57.675+01:00XCode 4.2 validating issuesToday I came across a weird behavior as I was trying to validate an app I had previously and successfully managed to archive.<br />
The build and archiving phases went fine (no errors).<br />
But as I tried to validate the new version of the app before publishing it to the app store, I was given the following error:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFd-x7j0dZvpE3pSp_fP-hOLIypwuM26ZfirUMue0QREt1VScKrQB4wKZNzm3bzA9MvDJxcWRVJVsYkxtcuNzTOTZN_IqiweWe-oDE-CWuiEWKik8dcxVwOWIB_Fy60LwQff27tKbZPSvS/s1600/Screen+shot+2011-12-14+at+10.23.12+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFd-x7j0dZvpE3pSp_fP-hOLIypwuM26ZfirUMue0QREt1VScKrQB4wKZNzm3bzA9MvDJxcWRVJVsYkxtcuNzTOTZN_IqiweWe-oDE-CWuiEWKik8dcxVwOWIB_Fy60LwQff27tKbZPSvS/s320/Screen+shot+2011-12-14+at+10.23.12+AM.png" width="320" /></a></div>
<br />
<br />
It came up XCode was compiling the app only for armv7 architectures.<br />
I solved the issue by changing the "Architectures" voice under Projects Settings -> Setting -> Architectures. I've deleted the previous setting (it was ARCHS_STANDARD_32_BIT) and added two new lines:<br />
<br />
armv7<br />
armv6Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-2996427176916549232011-12-04T15:33:00.001+01:002011-12-04T15:55:20.708+01:00Android PowerManager and wake locksToday I've tested the new version of my <a href="https://market.android.com/details?id=it.droidrunner.activity&feature=search_result#?t=W251bGwsMSwxLDEsIml0LmRyb2lkcnVubmVyLmFjdGl2aXR5Il0.">DroidRunner</a> Android app that now relies on a background service to track gps location updates.<br />
To my surprise when I finished my run, I've discovered that the GPS signal had been lost many times.<br />
That was strange since with the previous versions the GPS tracking was much more precise.<br />
After some googling I've found that I had forgot to add a <a href="http://developer.android.com/reference/android/os/PowerManager.WakeLock.html">wake lock</a> that prevents the CPU from going asleep. In previous versions that was happening much less frequently maybe because I didin't had any background service and as there was always an activity running, probably would prevent the system from going in a sleep mode.<br />
<br />
To add a wakelock just setup a new "use-permission" in AndroidManifest.xml:<br />
<br />
<br />
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="s1"><</span><span class="s2">uses-permission</span><span class="s3"> </span><span class="s4">android:name</span><span class="s3">=</span>"android.permission.WAKE_LOCK"<span class="s1">/></span></span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="s1"><br /></span></span></div>
<div class="p1">
<span class="s1"><span class="Apple-style-span" style="font-family: inherit;">Then, just decide which level of wake lock you want to have (for example, prevent CPU from going to sleep, with a </span></span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">PARTIAL_WAKE_LOCK</span>).</div>
<div class="p1">
Here is the list of possible options: <a href="http://developer.android.com/reference/android/os/PowerManager.html">PowerManager</a></div>
<div class="p1">
<span class="s1"><span class="Apple-style-span" style="font-family: inherit;"><br /></span></span></div>
<div class="p1">
<span class="s1"><span class="Apple-style-span" style="font-family: inherit;">This is the code snipped that can be used to request a wake lock:</span></span></div>
<div class="p1">
<span class="s1"><span class="Apple-style-span" style="font-family: inherit;"><br /></span></span></div>
<div class="p1">
<span class="s1"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">
</span></span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">PowerManager powerManager = (PowerManager)<span class="s1">this</span>.getApplicationContext().getSystemService(Context.<span class="s2">POWER_SERVICE</span>);</span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span><span class="s2">wakeLock</span> = powerManager.newWakeLock(PowerManager.<span class="s2">PARTIAL_WAKE_LOCK</span>, <span class="s2">"My Service"</span>);</span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: inherit;">Finally, request the wakelock and release it as soon as you don't use it:</span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div class="p1">
</div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="s1">wakeLock</span>.acquire();</span></div>
<div class="p2">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span></div>
<br />
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">...</span></div>
<div class="p1">
</div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="s1">wakeLock</span>.release();</span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="p1">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div class="p2">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<br />
<div class="p2">
<span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></div>
<br />
<div class="p2">
<span class="Apple-tab-span"> </span></div>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-76737785944133456882011-12-03T16:53:00.001+01:002011-12-03T16:57:57.318+01:00Create and push tagsWhen you've reached a stable version of your code and you've deployed it to users, it is a good practice to tag it.<br />
Start by create a local tag:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git tag v1.0</span><br />
<br />
Check that the tag is correctly created with:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git tag -l</span><br />
<br />
Then push it to your remote repository:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">git push --tags</span>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com0tag:blogger.com,1999:blog-6278175691080873971.post-74970161817946768952011-11-29T15:28:00.001+01:002012-01-11T11:48:44.520+01:00.gitignore file for Android projects<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">If you have an Android project and you want to share it you can setup your .gitignore file as follows:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.class</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.apk</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.ap_</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.dex</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.DS_Store</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*.proguard</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">.metadata/</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">bin/</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">gen/</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">local.properties</span><br />
<div>
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Don't add the .classpath entry or others will not be able to correctly setup your project.</span></div>
<div>
<span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">If you have a local git repository but you use git-svn as a bridge to commit changes on a SVN remote server, then be careful to manually add empty folders to SVN as Git ignores empty folders.</span></div>Adolfo Bulfonihttp://www.blogger.com/profile/02802024653709495611noreply@blogger.com1