<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-254432337824511900</id><updated>2012-01-27T14:08:24.143+01:00</updated><category term='xml'/><category term='Checkstyle'/><category term='View'/><category term='slider'/><category term='development boards'/><category term='git'/><category term='workflow'/><category term='NFC QR barcode'/><category term='attributes'/><category term='seminar'/><category term='custom view'/><category term='manifest'/><category term='beagleboard'/><category term='UI'/><category term='repo'/><category term='automation'/><category term='Security'/><category term='Android'/><category term='native'/><category term='atmel'/><category term='industrial'/><category term='presentations'/><category term='Platform'/><title type='text'>Enea Android Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.androidenea.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-2573702404087779210</id><published>2011-10-19T14:54:00.001+02:00</published><updated>2011-10-19T14:56:54.959+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='View'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='slider'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><category scheme='http://www.blogger.com/atom/ns#' term='custom view'/><title type='text'>Creating a custom view, part 1 - Graphics</title><content type='html'>It's not often I write about user interface and applications, but since I have now received a few question on the subject, I thought I would describe one rather common task - how to create a custom view.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s1600/final_result_portrait.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s320/final_result_portrait.png" width="240" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;An activity containing a horizontal and vertical slider.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;You will make your own customised slider, with the following features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Scale and stretch it depending on screen size, UI design and orientation.&lt;/li&gt;&lt;li&gt;Change position from the activity.&lt;/li&gt;&lt;li&gt;React to touches.&lt;/li&gt;&lt;li&gt;Set min and max values from xml or application code.&lt;/li&gt;&lt;/ul&gt;There are many other features that could be added, but I will only add them if requested enough times in the comments.&lt;br /&gt;&lt;br /&gt;The howto is divided into a few distinct steps, each describing a feature of the customised view.&lt;br /&gt;Depending on the purpose of your own custom view, not all of the steps may be needed. Furthermore I have divided the howto into three parts, to make it a bit less overwhelming:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Part I - Graphics - Draw the slider on the screen.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html"&gt;Part II - Interaction - Change the position of the indicator, from source code or by touching it.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html"&gt;Part III - Xml Attributes - Configure the layout of the slider from Xml.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The source code can be downloaded from github, and all steps are tagged in the git database. Each step will be preceded with the git command you need in order to look at the code step by step. If you prefer, you can just look at the latest commit in git, since that includes the complete example.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 24px; font-weight: bold;"&gt;Step 0. Download the source.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is really optional, but it's probably a good idea to have the code nearby so you can compare my code with yours.&lt;br /&gt;All these git commands are written for Linux command line. It should be very easy to from MS Windows or Mac OS as well, but unfortunately I have no experience in using git on any of those so you will have to find out yourself.&lt;br /&gt;&lt;br /&gt;Create a working directory and cd to it. I have called mine "enea":&lt;br /&gt;&lt;pre class="brush: bash"&gt;mkdir enea&lt;br /&gt;cd enea&lt;br /&gt;&lt;/pre&gt;Use git clone to get the project, and cd to it:&lt;br /&gt;&lt;pre class="brush: bash; first-line: 3"&gt;git clone git://github.com/androidenea/CustomView.git&lt;br /&gt;cd CustomView&lt;br /&gt;&lt;/pre&gt;You may now import the CustomView project to Eclipse.&lt;br /&gt;&lt;br /&gt;All further steps in this howto have been clearly tagged for easy access. Each step starts with one line showing the git command needed to get to the correct place.&lt;br /&gt;&lt;br /&gt;Please note that checking out a tag in git will get you to the correct version of the source code, but you are not allowed to commit any changes (unless you know what you are doing.)&lt;br /&gt;If you want to modify your code and store that in git, you will need to create your own branch first. This is not the time and place for a tutorial about git, but I highly recommend the book &lt;a href="http://progit.org/book/"&gt;"Pro Git"&lt;/a&gt; if you want to know more.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 1. Create a project&lt;/h2&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_1&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The first step will just give you a playground and a test harness in the shape of an activity.&lt;br /&gt;Grab the code from the git repository for an easy starting point, or do it yourself in Eclipse:&lt;br /&gt;Open Eclipse and create an Android project and fill in the following parametres:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Project name: CustomView&lt;/li&gt;&lt;li&gt;Build target: 1.6 or newer&lt;/li&gt;&lt;li&gt;Application name: CustomView&lt;/li&gt;&lt;li&gt;Package name: com.enea.training.customview&lt;/li&gt;&lt;li&gt;Create Activity: CustomViewActivity&lt;/li&gt;&lt;li&gt;Min SDK version: 4&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Click finish to create your project. If you don't really understand what all those things actually mean, you will have a hard time understanding the other steps, as this tutorial is rather advanced. Read through a few other beginner's tutorials first and then you are most welcome back here.&lt;br /&gt;&lt;br /&gt;To get a good base layout for the tests, and to get an idea of what this whole tutorial is about, you should replace the LinearLayout in main.xml with a RelativeLayout containing a SeekBar. The contents of main.xml should look like this:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;RelativeLayout &lt;br /&gt;    xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;    android:layout_width="fill_parent"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    &amp;gt;&lt;br /&gt;    &amp;lt;SeekBar android:id="@+id/slider"&lt;br /&gt;      android:layout_height="wrap_content"&lt;br /&gt;      android:layout_width="fill_parent"&lt;br /&gt;      android:layout_alignParentLeft="true"&lt;br /&gt;      android:layout_alignParentTop="true"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&amp;lt;/RelativeLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;That's it for step 1. That wasn't too bad was it?&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-iAMVU7Tl4xw/Tp67pZgSp5I/AAAAAAAAAE4/JCfG1b9M4XY/s1600/step_1_landscape.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-iAMVU7Tl4xw/Tp67pZgSp5I/AAAAAAAAAE4/JCfG1b9M4XY/s1600/step_1_landscape.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Step 1. Standard SeekBar.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;h2&gt;Step 2. Add a custom view.&lt;/h2&gt;&lt;br /&gt;This is by far the biggest step in this howto. We will add bitmaps and source code and we will also replace the SeekBar in step 1 with the custom view. We will do this in small steps to keep things apart.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 2.1 Bitmaps&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_2_1&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;There are three bitmaps that will be needed. I suggest you grab the ones from the git repository, even if you are implementing the rest without looking at my sample. The reason is that designing stretchable bitmaps is not within the scope of this tutorial. There are very good guidelines on how to design stretchable, or NinePatch, bitmaps on the Android SDK web page, here: &lt;a href="http://developer.android.com/guide/developing/tools/draw9patch.html"&gt;Draw 9-patch&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Copy the whole of directory res/drawable to your project. I have not spent much time on the graphics, other than making sure to use the nice Enea-red colour, but the bitmaps do scale well and will not look too shabby on anything from my small 2.6" QVGA phone to my nice 10.1" WXGA tablet.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 2.2 Slider class&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_2_2&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Ok, so let's try to make use of those bitmaps, shall we?&lt;br /&gt;Create a new class in the same package as earlier, and let it extend android.widget.View. In Eclipse, right-click on the package and select &lt;i&gt;New-&amp;gt;Class&lt;/i&gt;.&lt;br /&gt;Fill in the blanks as follows:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Name: CustomSlider&lt;/li&gt;&lt;li&gt;Superclass: android.view.View&lt;/li&gt;&lt;li&gt;Generate constructors from superclass&lt;/li&gt;&lt;/ul&gt;Everything else should be left as default. Click &lt;i&gt;Finish&lt;/i&gt; to create the class.&lt;br /&gt;&lt;br /&gt;The two simpler constructors can just call to the most flexible one, with &lt;i&gt;0&lt;/i&gt; or &lt;i&gt;null&lt;/i&gt; as parameters, like so (the line numbers should roughly match the source code in git, assuming that you have checked out the corresponding step):&lt;br /&gt;&lt;pre class="brush:java; first-line:14"&gt;public CustomSlider(final Context context) {&lt;br /&gt;  this(context, null, 0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public CustomSlider(final Context context, final AttributeSet attrs) {&lt;br /&gt;  this(context, attrs, 0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The last constructor will need to do a few things though. It will be extended as we go along, but for now all that is needed is to point out the bitmaps to be used. For that you will also need to add references to the bitmaps.&lt;br /&gt;Add the following members to your class:&lt;br /&gt;&lt;pre class="brush:java; first-line:11"&gt;private final Drawable mIndicator;&lt;br /&gt;private final Drawable mBackground;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To initialise them, you will need a handle to the resources, and then set them, using the resource reference id.&lt;br /&gt;Your third constructor should look like this:&lt;br /&gt;&lt;pre class="brush:java; first-line:22"&gt;public CustomSlider(Context context, AttributeSet attrs, int defStyle) {&lt;br /&gt;  super(context, attrs, defStyle);&lt;br /&gt;&lt;br /&gt;  final Resources res = context.getResources();&lt;br /&gt;  mIndicator = res.getDrawable(R.drawable.indicator_horizontal);&lt;br /&gt;  mBackground = res.getDrawable(R.drawable.background_horizontal);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let Eclipse add any missing imports that might be needed.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 2.3 onDraw&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_2_3&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;All the drawing is happening in &lt;i&gt;onDraw()&lt;/i&gt;. This method is potentially called quite often, so make a good habit out of making it as fast as possible. In particular, avoid allocating and freeing memory in it.&lt;br /&gt;In this example, &lt;i&gt;onDraw()&lt;/i&gt; will calculate the position for the indicator and draw the background, followed by the indicator, positioned relative to the background's end points.&lt;br /&gt;For this to work there are a few member fields needed. First of all the normalised position of the indicator:&lt;br /&gt;&lt;pre class="brush:java; first-line:15"&gt;private float mMin;&lt;br /&gt;  private float mMax;&lt;br /&gt;  private float mPosition;&lt;br /&gt;&lt;/pre&gt;These need to be initialised in the constructor. For now just assume that the slider goes from -1.0 to 1.0 and that the indicator is positioned in the middle.&lt;br /&gt;Add the following lines to the bottom of the constructor:&lt;br /&gt;&lt;pre class="brush:java; first-line:39"&gt;mMin = -1.0f;&lt;br /&gt;    mMax = 1.0f;&lt;br /&gt;    mPosition = (mMax - mMin) / 2 + mMin;&lt;br /&gt;&lt;/pre&gt;Then a few member fields are needed to help out with the drawing. We need somewhere to store the view's absolute drawing area:&lt;br /&gt;&lt;pre class="brush:java; first-line:18"&gt;private Rect mViewRect;&lt;br /&gt;&lt;/pre&gt;The offset, min and max absolute positions for the indicator are also stored, so we don't need to recalculate them every time.&lt;br /&gt;&lt;pre class="brush:java; first-line:19"&gt;private int mIndicatorOffset;&lt;br /&gt;  private int mIndicatorMaxPos;&lt;br /&gt;  private int mIndicatorMinPos;&lt;br /&gt;&lt;/pre&gt;And finally there's the actual onDraw method:&lt;br /&gt;&lt;pre class="brush:java; first-line:44"&gt;@Override&lt;br /&gt;  protected void onDraw(final Canvas canvas) {&lt;br /&gt;&lt;/pre&gt;First, check if the absolute drawing area is null, and if it is, fill in all the absolute values:&lt;br /&gt;&lt;pre class="brush:java; first-line:46"&gt;if (mViewRect == null) {&lt;br /&gt;      mViewRect = new Rect();&lt;br /&gt;      getDrawingRect(mViewRect);&lt;br /&gt;      mIndicatorOffset = mIndicator.getIntrinsicWidth();&lt;br /&gt;      mIndicatorMaxPos = mViewRect.right - mIndicatorOffset;&lt;br /&gt;      mIndicatorMinPos = mViewRect.left + mIndicatorOffset;&lt;br /&gt;      mBackground.setBounds(mViewRect.left, mViewRect.top, mViewRect.right,&lt;br /&gt;          mViewRect.bottom);&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;Now it's time to calculate the position of the indicator bar, based on min and max values, offset, etc. Get some local variables to hold the position and edges of the indicator, and calculate the position:&lt;br /&gt;&lt;pre class="brush:java; first-line:56"&gt;final float pos;&lt;br /&gt;    final int left;&lt;br /&gt;    final int right;&lt;br /&gt;    final int top;&lt;br /&gt;    final int bottom;&lt;br /&gt;&lt;br /&gt;    pos = mIndicatorMinPos&lt;br /&gt;        + ((mIndicatorMaxPos - mIndicatorMinPos) / (mMax - mMin))&lt;br /&gt;        * (mPosition - mMin);&lt;br /&gt;&lt;/pre&gt;When setting the drawing bounds for the indicator, there are some calculations to be made, since pos above is the centerpoint of the indicator, and not one of the edges:&lt;br /&gt;&lt;pre class="brush:java; first-line:64"&gt;left = (int) pos - (mIndicator.getIntrinsicWidth() / 2);&lt;br /&gt;    top = mViewRect.centerY() - (mIndicator.getIntrinsicHeight() / 2);&lt;br /&gt;    right = left + mIndicator.getIntrinsicWidth();&lt;br /&gt;    bottom = top + mIndicator.getIntrinsicHeight();&lt;br /&gt;    mIndicator.setBounds(left, top, right, bottom);&lt;br /&gt;&lt;/pre&gt;And finally, it's time to draw (don't forget the closing bracket):&lt;br /&gt;&lt;pre class="brush:java; first-line:70"&gt;mBackground.draw(canvas);&lt;br /&gt;    mIndicator.draw(canvas);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;As you have perhaps already figured out, the system will know where to draw the bitmaps through the call to &lt;i&gt;setBounds()&lt;/i&gt; for each bitmap. The rest where just there to calculate the bounds.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 2.4 onMeasure&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_2_4&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;One more thing needs to be added to the CustomView class, before we can start using it in step 2.5. The layout engine still don't know how large our view is. To find out, it will need to measure the view. Whenever that happens, there will be a call to &lt;i&gt;onMeasure()&lt;/i&gt;.&lt;br /&gt;The implementation of &lt;i&gt;onMeasure()&lt;/i&gt; is far simpler than &lt;i&gt;onDraw()&lt;/i&gt;. All that is needed is to specify the width and the height of the view.&lt;br /&gt;&lt;br /&gt;First of all there needs to be a call to the &lt;i&gt;super.onMeasure()&lt;/i&gt;. This will set the width and height to maximum possible values, based on your layout parameters, such as fill_parent (or match_parent) and wrap_contents, margins, etc.:&lt;br /&gt;&lt;pre class="brush:java; first-line:74"&gt;@Override&lt;br /&gt;  protected void onMeasure(final int widthMeasureSpec,&lt;br /&gt;     final int heightMeasureSpec) {&lt;br /&gt;    super.onMeasure(widthMeasureSpec, heightMeasureSpec);&lt;br /&gt;&lt;/pre&gt;For horizontal rendering of the slider view, the width should be the maximum possible, but the height should be limited to the height of the indicator (if you use the bitmaps from my sample project.):&lt;br /&gt;&lt;pre class="brush:java; first-line:79"&gt;setMeasuredDimension(getMeasuredWidth(), mIndicator.getIntrinsicHeight());&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;As usual, don't forget the closing bracket. (If you are wondering where the code for vertical rendering is, you will have to be patient, as it won't be added until step 5.)&lt;br /&gt;&lt;br /&gt;Phew, that's it with the implementation for now. It will still not show up on screen, though. That is because it hasn't been added to the &lt;i&gt;main.xml&lt;/i&gt; layout file. So let's do that.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 2.5 Use the view.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;git checkout step_2_5&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The final thing to do in order to see the work we have just done is to replace the SeekBar with the CustomSlider. There is only one thing to change to do that - In the xml file, replace SeekBar with com.enea.training.customview.CustomSlider. Note that the package name must be included, or the view will not be found by the layout engine. Here is what that edited line should look like:&lt;br /&gt;&lt;pre class="brush:xml; first-line:7"&gt;&amp;lt;com.enea.training.customview.CustomSlider android:id="@+id/slider"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you run your project now, you should see the new shiny slider stretched horizontally across the top of the screen. Tilt your Android device between landscape and portrait and you will see that the bitmaps are nicely stretched. You may also want to change the constructor to initialise mPosition to different values and see that the indiator is placed correctly. Usually the end points are the trickiest ones to get right, so try setting mPosition to mMin and mMax respectively and try the view in both portrait and landscape to make sure it looks good.&lt;br /&gt;&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Vz0mSa4ZIkY/Tp69LwNpkBI/AAAAAAAAAFA/E4Ve-ZsV9jI/s1600/step_2_5_portrait.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Vz0mSa4ZIkY/Tp69LwNpkBI/AAAAAAAAAFA/E4Ve-ZsV9jI/s1600/step_2_5_portrait.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;SeekBar replaced with CustomSlider&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;Custom&lt;/span&gt;&lt;/div&gt;There are a few situations when this would be all you want to do with a view, but most likely you want to be able to change the slider indicator from your activity and also interact with it by touching it. Or maybe you want a vertical slider instead?&lt;br /&gt;&lt;br /&gt;Finally, if you want simple ways of reusing it, you probably want to be able to set things like min and max directly in the xml file.&lt;br /&gt;&lt;br /&gt;So let's do all that. Get some fresh coffee and head over to the second part of this tutorial.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #999999;"&gt;Part I. Graphics&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html"&gt;Part II - Interaction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html"&gt;Part III - Xml Attributes&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Please use the comments field if you have any questions.&lt;br /&gt;&lt;br /&gt;/Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-2573702404087779210?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/2573702404087779210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/2573702404087779210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/2573702404087779210'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html' title='Creating a custom view, part 1 - Graphics'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s72-c/final_result_portrait.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-1771885934066906670</id><published>2011-10-19T14:49:00.001+02:00</published><updated>2011-10-19T14:57:47.471+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='View'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='slider'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><category scheme='http://www.blogger.com/atom/ns#' term='custom view'/><title type='text'>Creating a custom view, part 3 - Xml Attributes</title><content type='html'>This is the final part in the series of articles describing how to create a custom view.&lt;br /&gt;For the other parts, follow these links:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html"&gt;Part I - Graphics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html"&gt;Part II - Interaction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #999999;"&gt;Part III - Xml Attributes&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In this part, you will see how to make your slider vertical, and how to set attributes from within xml, just the way you do with all the built-in views.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 5 Vertical slider&lt;/h2&gt;&lt;br /&gt;Making the slider vertical is slightly more challenging than step 4. The view must be aware of its orientation, and all position calculations must detect orientation. The complexity of this step means that we are back to doing sub-steps.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 5.1 A Vertical member.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_5_1&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The orientation of the slider can only be vertical or horizontal (I leave it to you as an exercise to implement a diagonal slider), so storing orientation can be done in a boolean:&lt;br /&gt;&lt;pre class="brush:java toolbar:false first-line:27"&gt;private boolean mIsVertical;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;i&gt;mIsVertical&lt;/i&gt; will need to be initialised in the constructor. It's just going to be hard-coded to &lt;i&gt;true&lt;/i&gt; here, until things improve in step 6.&lt;br /&gt;Near the top of the constructor, just after the call to &lt;i&gt;super&lt;/i&gt;, this line should be added:&lt;br /&gt;&lt;pre class="brush:java first-line:41"&gt;mIsVertical = true;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Obviously, the slider will not become vertical just because of this, that's why there are a few more steps.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 5.2 Pick your bitmaps.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_5_2&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Now that there is a boolean to check for orientation, it's time to act upon it. The first thing to do is to select the correct bitmaps. In the constructor, add an &lt;i&gt;if&lt;/i&gt; statement that will initalise the &lt;i&gt;mIndicator&lt;/i&gt; and &lt;i&gt;mBackground&lt;/i&gt; drawables accordingly:&lt;br /&gt;&lt;pre class="brush:java first-line:44"&gt;if (mIsVertical) {&lt;br /&gt;      mIndicator = res.getDrawable(R.drawable.indicator_vertical);&lt;br /&gt;      mBackground = res.getDrawable(R.drawable.background_vertical);&lt;br /&gt;    } else {&lt;br /&gt;      mIndicator = res.getDrawable(R.drawable.indicator_horizontal);&lt;br /&gt;      mBackground = res.getDrawable(R.drawable.background_horizontal);&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Step 5.3 onTouchListener revisited.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_5_3&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The calculations in the touch listener should also be updated. This is where it becomes a bit tricky. For horizontal orientation the &lt;i&gt;mMin&lt;/i&gt; corresponds to &lt;i&gt;mIndicatorMinPos&lt;/i&gt;, that is pixels and values are growing in the same direction. Whereas for vertical orientation &lt;i&gt;mMin&lt;/i&gt; corresponds to &lt;i&gt;mIndicatorMaxPos&lt;/i&gt;, that is pixels and values grow in opposite directions.&lt;br /&gt;In the touch listener that is located in the constructor, surround the calculations with the following if-statement:&lt;br /&gt;&lt;pre class="brush:java first-line:59"&gt;if (mIsVertical) {&lt;br /&gt;          pos = (mMax - ((mMax - mMin) / (mIndicatorMinPos - mIndicatorMaxPos))&lt;br /&gt;              * event.getY());&lt;br /&gt;        } else {&lt;br /&gt;          pos = (mMin + ((mMax - mMin) / (mIndicatorMaxPos - mIndicatorMinPos))&lt;br /&gt;              * event.getX());&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;Note how the calculation of pos differs.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 5.4 Improve the drawings.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_5_4&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The &lt;i&gt;onDraw()&lt;/i&gt; and &lt;i&gt;onMeasure()&lt;/i&gt; will also need to be dependent on the orientation. Let's do &lt;i&gt;onDraw()&lt;/i&gt; first.&lt;br /&gt;The first part of &lt;i&gt;onDraw()&lt;/i&gt; initialises indicator min, max and offset values, in relation to the view's drawing rectangle. Surround the initialisation with the following &lt;i&gt;if&lt;/i&gt; statement:&lt;br /&gt;&lt;pre class="brush:java first-line:77"&gt;if (mIsVertical) {&lt;br /&gt;        mIndicatorOffset = mIndicator.getIntrinsicHeight();&lt;br /&gt;        mIndicatorMaxPos = mViewRect.top + mIndicatorOffset;&lt;br /&gt;        mIndicatorMinPos = mViewRect.bottom - mIndicatorOffset;&lt;br /&gt;      } else {&lt;br /&gt;        mIndicatorOffset = mIndicator.getIntrinsicWidth();&lt;br /&gt;        mIndicatorMaxPos = mViewRect.right - mIndicatorOffset;&lt;br /&gt;        mIndicatorMinPos = mViewRect.left + mIndicatorOffset;&lt;br /&gt;      }&lt;br /&gt;&lt;/pre&gt;Note how max and min relates to the &lt;i&gt;mViewRect&lt;/i&gt; coordinates.&lt;br /&gt;&lt;br /&gt;The second part of &lt;i&gt;onDraw()&lt;/i&gt; calculates the real position of the indicator, based on the values above. Only &lt;i&gt;pos&lt;/i&gt; and &lt;i&gt;top&lt;/i&gt; &lt;i&gt;left&lt;/i&gt; corner will need to modified for the indicator, since the other corners are relative to this one. Surround the calculations with the following:&lt;br /&gt;&lt;pre class="brush:java first-line:95"&gt;if (mIsVertical) {&lt;br /&gt;      pos = mIndicatorMaxPos&lt;br /&gt;          + ((mIndicatorMinPos - mIndicatorMaxPos) / (mMax - mMin))&lt;br /&gt;          * (mMax - mPosition);&lt;br /&gt;      left = mViewRect.centerX() - (mIndicator.getIntrinsicWidth() / 2);&lt;br /&gt;      top = (int) pos - (mIndicator.getIntrinsicHeight() / 2);&lt;br /&gt;    } else {&lt;br /&gt;      pos = mIndicatorMinPos&lt;br /&gt;          + ((mIndicatorMaxPos - mIndicatorMinPos) / (mMax - mMin))&lt;br /&gt;          * (mPosition - mMin);&lt;br /&gt;      left = (int) pos - (mIndicator.getIntrinsicWidth() / 2);&lt;br /&gt;      top = mViewRect.centerY() - (mIndicator.getIntrinsicHeight() / 2);&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, &lt;i&gt;onMeasure()&lt;/i&gt; will need to be modified. This is much simpler, since no calculations are needed. Surround the setter with the following:&lt;br /&gt;&lt;pre class="brush:java first-line:117"&gt;if (mIsVertical) {&lt;br /&gt;      setMeasuredDimension(mIndicator.getIntrinsicWidth(), getMeasuredHeight());&lt;br /&gt;    } else {&lt;br /&gt;      setMeasuredDimension(getMeasuredWidth(), mIndicator.getIntrinsicHeight());&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Done. You are now finished with step 5. Run your project and make sure the slider works as expected. Change the initialisation of mIsVertical in the constructor to make sure that you haven't broken the horizontal layout.&lt;br /&gt;Note that when rendering the slider vertically, it pushes the reset button off the screen. Correcting it would require a modification of your activity's layout, which will be done next.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 6 Add key-value attributes in xml.&lt;/h2&gt;&lt;br /&gt;Almost there, the only thing left in this tutorial is to add some attributes that can be set from within the xml layout. Let's start with specifying the attributes.&lt;br /&gt;I'm not going to go too far, but at least it makes sense to be able to set orientation, min and max from the xml. Once you've seen how to do this, adding other attributes should be easy.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 6.1 xml modifications.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_6_1&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Right-click on your project and select New-&amp;gt;Android xml file.&lt;br /&gt;Specify the file name "&lt;i&gt;attrs.xml&lt;/i&gt;" and select the &lt;i&gt;Values&lt;/i&gt; radio button. Click Finish to generate the file.&lt;br /&gt;Open up the xml view of &lt;i&gt;attrs.xml&lt;/i&gt;. This is where the attributes should go.&lt;br /&gt;The node to use is called &lt;i&gt;declare-stylable&lt;/i&gt;, and is used to identify a group of attributes. The sub-nodes are all of type &lt;i&gt;attr&lt;/i&gt; and contains name and type of the attribute. Min and max are floats, whereas orientation is vertical or horizontal.&lt;br /&gt;Your &lt;i&gt;attrs.xml&lt;/i&gt; file should look like this:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;resources&amp;gt;&lt;br /&gt;  &amp;lt;declare-styleable name="CustomSlider"&amp;gt;&lt;br /&gt;    &amp;lt;attr name="orientation"&amp;gt;&lt;br /&gt;      &amp;lt;enum name="horizontal" value="0" /&amp;gt;&lt;br /&gt;      &amp;lt;enum name="vertical" value="1" /&amp;gt;&lt;br /&gt;    &amp;lt;/attr&amp;gt;&lt;br /&gt;    &amp;lt;attr name="max" format="float"/&amp;gt;&lt;br /&gt;    &amp;lt;attr name="min" format="float"/&amp;gt;&lt;br /&gt;  &amp;lt;/declare-styleable&amp;gt;&lt;br /&gt;&amp;lt;/resources&amp;gt;&lt;br /&gt;&lt;/pre&gt;This provides three key-value pairs that can be set for the slider. It's worth noting that there are other ways of specifying attributes. For example, if you want to re-use the enum for orientation, you may declare it outside of the &lt;br /&gt;&lt;i&gt;&lt;declare-stylable&gt;&lt;/declare-stylable&gt;&lt;/i&gt; tag and just refer to it. Just ask, and I will in the comments describe how to do that.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 6.2 Modified constructor.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_6_2&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;There is one more thing to do to get this to work - modify the constructor to make use of the new attributes.&lt;br /&gt;This is really quite easy. One of the input parameters to the constructor is an &lt;i&gt;AttributeSet&lt;/i&gt;, containing all the attributes for your view.&lt;br /&gt;&lt;br /&gt;From that, you need to extract the attributes you are interested in.&lt;br /&gt;&lt;br /&gt;At the top of your constructor, right after the call to &lt;i&gt;super()&lt;/i&gt;, you should add the following lines to get a &lt;i&gt;TypedArray&lt;/i&gt; with the attributes:&lt;br /&gt;&lt;pre class="brush:java first-line:42"&gt;final TypedArray a = context.obtainStyledAttributes(attrs,&lt;br /&gt;        R.styleable.CustomSlider);&lt;br /&gt;&lt;/pre&gt;Now, instead of just hard-coding &lt;i&gt;mIsVertical&lt;/i&gt; to true or false, you should grab the orientation from your attributes. But since the &lt;i&gt;orientation&lt;/i&gt; attribute&lt;br /&gt;translates &lt;i&gt;horizontal/vertical&lt;/i&gt; to an integer, based on the enum, you will need your java code to turn it into true or false. This code should replace the "&lt;i&gt;mIsVertical=true&lt;/i&gt;" statement:&lt;br /&gt;&lt;pre class="brush:java first-line:44"&gt;final int vertical = a.getInt(R.styleable.CustomSlider_orientation, 0);&lt;br /&gt;    mIsVertical = (vertical != 0);&lt;br /&gt;&lt;/pre&gt;Look at the help for &lt;i&gt;getInt()&lt;/i&gt; and make sure that you understand what the parameters mean.&lt;br /&gt;&lt;br /&gt;The min and max values are done in a similar way, but they are already floats, so no extra treatment is necessary. Replace the &lt;i&gt;mMin&lt;/i&gt; and &lt;i&gt;mMax&lt;/i&gt; initialisation statements with the following:&lt;br /&gt;&lt;pre class="brush:java first-line:47"&gt;final int max = a.getInt(R.&amp;gt;final float max = a.getFloat(R.styleable.CustomSlider_max, 1.0f);&lt;br /&gt;    final float min = a.getFloat(R.styleable.CustomSlider_min, -1.0f);&lt;br /&gt;    setMinMax(min, max);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ok, done with the slider. Let's put that latest piece of code to some use.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 6.3 Attributes in layout&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_6_3&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Once the new attributes are declared, you can refer to them from your &lt;i&gt;main.xml&lt;/i&gt; layout file.&lt;br /&gt;You will need to add the namespace to the layout and then obviously set the attributes for the &lt;i&gt;CustomSlider&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;The namespace is an attribute for the &lt;i&gt;RelativeLayout&lt;/i&gt;, so the first few lines in &lt;i&gt;main.xml&lt;/i&gt; should now look like this:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;relativelayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:customview="http://schemas.android.com/apk/res/com.enea.training.customview"&gt;&lt;br /&gt;&lt;/relativelayout&gt;&lt;/pre&gt;Once that is added, it's just a matter of setting the attributes for the slider views. The updated slider tag should look like this:&lt;br /&gt;&lt;pre class="brush:xml first-line:8"&gt;&amp;lt;com.enea.training.customview.CustomSlider android:id="@+id/slider_horizontal"&lt;br /&gt;      CustomView:orientation="horizontal"&lt;br /&gt;      CustomView:min="0.0"&lt;br /&gt;      CustomView:max="100.0"&lt;br /&gt;      android:layout_height="wrap_content"&lt;br /&gt;      android:layout_width="fill_parent"&lt;br /&gt;      android:layout_alignParentLeft="true"&lt;br /&gt;      android:layout_alignParentTop="true"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&lt;/pre&gt;To make things a bit more interesting, you could add another slider, and make it vertical:&lt;br /&gt;&lt;pre class="brush:xml first-line:17"&gt;&amp;lt;com.enea.training.customview.CustomSlider android:id="@+id/slider_vertical"&lt;br /&gt;      CustomView:orientation="vertical"&lt;br /&gt;      CustomView:min="-50.0"&lt;br /&gt;      CustomView:max="50.0"&lt;br /&gt;      android:layout_height="fill_parent"&lt;br /&gt;      android:layout_width="wrap_content"&lt;br /&gt;      android:layout_alignParentLeft="true"&lt;br /&gt;      android:layout_below="@+id/slider_horizontal"&lt;br /&gt;      android:layout_alignParentBottom="true"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, the new attributes are being set exactly the same way as the standard attributes, the only difference is the namespace.&lt;br /&gt;&lt;br /&gt;That new slider needs some code in the activity as well. You will need a new member field and a new position listener, and &lt;i&gt;displayValues()&lt;/i&gt; will need to display the vertical value.&lt;br /&gt;Furthermore, since the horizontal slider now gets the initial values from xml, there is no need to call the setters in &lt;i&gt;onCreate()&lt;/i&gt;.&lt;br /&gt;The &lt;i&gt;onReset()&lt;/i&gt; callback method for the button will also need to be updated to reset both sliders.&lt;br /&gt;Here is the complete listing of the activity. As you can see, it's just a matter of duplicating the code of the horizontal slider for the vertical.&lt;br /&gt;&lt;pre class="brush:java first-line:10"&gt;public class CustomViewActivity extends Activity {&lt;br /&gt;  private TextView     mValues;&lt;br /&gt;  private CustomSlider mSliderHorizontal;&lt;br /&gt;  private CustomSlider mSliderVertical;&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void onCreate(final Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;    setContentView(R.layout.main);&lt;br /&gt;&lt;br /&gt;    mValues = (TextView) findViewById(R.id.values);&lt;br /&gt;&lt;br /&gt;    mSliderHorizontal = (CustomSlider) findViewById(R.id.slider_horizontal);&lt;br /&gt;    mSliderHorizontal.setPositionListener(new CustomSliderPositionListener() {&lt;br /&gt;      public void onPositionChange(final float newPosition) {&lt;br /&gt;        displayValues();&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;    mSliderVertical = (CustomSlider) findViewById(R.id.slider_vertical);&lt;br /&gt;    mSliderVertical.setPositionListener(new CustomSliderPositionListener() {&lt;br /&gt;      public void onPositionChange(final float newPosition) {&lt;br /&gt;        displayValues();&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    displayValues();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  void displayValues() {&lt;br /&gt;    final String str = String.format("Horizontal: %3.2f\nVertical: %3.2f",&lt;br /&gt;        mSliderHorizontal.getPosition(), mSliderVertical.getPosition());&lt;br /&gt;    mValues.setText(str);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void onReset(final View v) {&lt;br /&gt;    float min = mSliderHorizontal.getMin();&lt;br /&gt;    float max = mSliderHorizontal.getMax();&lt;br /&gt;    float newPos = (max - min) / 2 + min;&lt;br /&gt;    mSliderHorizontal.setPosition(newPos);&lt;br /&gt;&lt;br /&gt;    min = mSliderVertical.getMin();&lt;br /&gt;    max = mSliderVertical.getMax();&lt;br /&gt;    newPos = (max - min) / 2 + min;&lt;br /&gt;    mSliderVertical.setPosition(newPos);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it! Try your application again, perhaps a few times while changing the attributes in &lt;i&gt;main.xml&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s1600/final_result_portrait.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s320/final_result_portrait.png" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-4gyAp4t5Q4E/TpRTDvLYu0I/AAAAAAAAAEs/a3umYpHA84U/s1600/final_result_portrait_landscape.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/-4gyAp4t5Q4E/TpRTDvLYu0I/AAAAAAAAAEs/a3umYpHA84U/s320/final_result_portrait_landscape.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Where to go from here&lt;/h2&gt;Even though this series of articles is a long read, the actual steps are not that difficult.&lt;br /&gt;&lt;br /&gt;The view just implemented is far from complete, but I do believe it's a good starting point. Things you may want to add are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make the view retain values between orientation changes.&lt;/li&gt;&lt;li&gt;Different colour of the indicator when touched, like the standard views.&lt;/li&gt;&lt;li&gt;React to long clicks or double clicks.&lt;/li&gt;&lt;li&gt;Displaying the value within the view instead of a separate view.&lt;/li&gt;&lt;li&gt;Animations, 3D graphics.&lt;/li&gt;&lt;/ul&gt;Keep in mind though, that this example extends a standard View. If you only want to modify one of the already existing views, for example a new behaviour for a button, you can opt for the much simpler route of just extending that type of view and only modify the things you need.&lt;br /&gt;&lt;br /&gt;Now go and create astonishing views for your applications, and feel free to use the comments field below for any questions.&lt;br /&gt;&lt;br /&gt;If you don't want to use the back button to read the articles again, you can use these links:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html"&gt;Part I - Graphics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html"&gt;Part II - Interaction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #999999;"&gt;Part III - Xml Attributes&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Thanks for reading. Please use the comments field if you have any questions.&lt;br /&gt;&lt;br /&gt;/Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-1771885934066906670?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/1771885934066906670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1771885934066906670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1771885934066906670'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html' title='Creating a custom view, part 3 - Xml Attributes'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-811uuaXdiMM/TpRTDXjWCnI/AAAAAAAAAEk/S-5zGR26ctU/s72-c/final_result_portrait.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-4744494746674538981</id><published>2011-10-19T14:47:00.003+02:00</published><updated>2011-10-19T14:58:48.563+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='View'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='slider'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='attributes'/><category scheme='http://www.blogger.com/atom/ns#' term='custom view'/><title type='text'>Creating a custom view, part 2 - Interaction</title><content type='html'>This is the second part in my article about how to create a custom view in Android.&lt;br /&gt;Please follow these links for the other parts:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html"&gt;Part I - Graphics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #999999;"&gt;Part II - Interaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html"&gt;Part III - Xml Attributes&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;In this part of the article, the slider will get some useful functionality, like being able to position the indicator from the activity, and react on touches.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Step 3 Change indicator position from the activity.&lt;/h2&gt;&lt;br /&gt;This step is far from the complexity in step 2, but still complex enough to warrant a few substeps.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 3.1 Setters and getters.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_3_1&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The requirement for this step was to be able to change the indicator position, but it makes sense to also make it possible to also alter the min and max values.&lt;br /&gt;&lt;br /&gt;The getters are easy, but the setters need a few extras.&lt;br /&gt;Let Eclipse do the easy part for you, by right-clicking on your class and selecting &lt;i&gt;Source-&amp;gt;Generate Getters and Setters&lt;/i&gt;. Tick &lt;i&gt;mMin&lt;/i&gt;, &lt;i&gt;mMax&lt;/i&gt; and &lt;i&gt;mPosition&lt;/i&gt; and make sure to generate both getter and setter for mPosition and mMin. You don't need one for &lt;i&gt;mMax&lt;/i&gt;, for reasons that will become clear in a moment.&lt;br /&gt;After the code has been generated, you probably want to tidy up the method names slightly. Your getters should look something like this:&lt;br /&gt;&lt;pre class="brush:java; first-line:82"&gt;public float getMin() {&lt;br /&gt;    return mMin;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public float getMax() {&lt;br /&gt;    return mMax;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public float getPosition() {&lt;br /&gt;    return mPosition;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;As I said, the setters require a few extra lines. Since calling a setter will possibly alter a visible view, the view should be invalidated. But since invalidating views trigger a redrawing of it and possibly neighbouring views you should not invalidate unless needed. Furthermore you probably don't want the position to be outside of min and max, so you should check for that. Your setter for &lt;i&gt;mPosition&lt;/i&gt; should thus look like this:&lt;br /&gt;&lt;pre class="brush:java; first-line:94"&gt;public void setPosition(float position) {&lt;br /&gt;    position = within(mMin, mMax);&lt;br /&gt;&lt;br /&gt;    if(position != mPosition) {&lt;br /&gt;      mPosition = position;&lt;br /&gt;      invalidate();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;You will also need to implement that helper method, &lt;i&gt;within()&lt;/i&gt;. It should look something like this:&lt;br /&gt;&lt;pre class="brush:java; first-line:102"&gt;private float within(float position, final float min, final float max) {&lt;br /&gt;    if (position &amp;lt; min) {&lt;br /&gt;      position = min;&lt;br /&gt;    }&lt;br /&gt;    if (position &amp;gt; max) {&lt;br /&gt;      position = max;&lt;br /&gt;    }&lt;br /&gt;    return position;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is the reason for not generating a setter for &lt;i&gt;mMax&lt;/i&gt;. For the slider to work properly, &lt;i&gt;mMin&lt;/i&gt; must always be smaller than &lt;i&gt;mMax&lt;/i&gt;, and the indicator must always be positioned somewhere in between min and max. That's why &lt;i&gt;mMin&lt;/i&gt; and &lt;i&gt;mMax&lt;/i&gt; must be set in the same method. The setter should check min and max, and throw an exception if they are wrong, and it should also adjust the position of the indicator. The adjustment can be done by reusing the setter for the position, like this (renaming &lt;i&gt;setMin&lt;/i&gt; to &lt;i&gt;setMinMax&lt;/i&gt;):&lt;br /&gt;&lt;pre class="brush:java; first-line:112"&gt;public void setMinMax(final float min, final float max) {&lt;br /&gt;    if ((min != mMin) || (max != mMax)) {&lt;br /&gt;      if (min &amp;gt; max) {&lt;br /&gt;        throw new IllegalArgumentException(&lt;br /&gt;            "setMinMax: min must be smaller than max.");&lt;br /&gt;      }&lt;br /&gt;      mMin = min;&lt;br /&gt;      mMax = max;&lt;br /&gt;      setPosition(mPosition);&lt;br /&gt;      invalidate();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Step 3.2 onPositionChanged&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_3_2&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Being able to set and get the position is handy, but you will also need some way for the view to tell the activity that values have changed.&lt;br /&gt;For this you will need a listener interface for your view and your activity needs to implement it in a usual manner. (The activity will be modified in the next step.)&lt;br /&gt;Adding an listener interface is just a matter of specifying what should go in the interface and which object that should be tied to it.&lt;br /&gt;First the interface. Put this into your class:&lt;br /&gt;&lt;pre class="brush:java; first-line:12"&gt;interface CustomSliderPositionListener {&lt;br /&gt;    void onPositionChange(float newPosition);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;A new member field is also needed:&lt;br /&gt;&lt;pre class="brush:java; first-line:25"&gt;private CustomSliderPositionListener mPositionListener;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The field will need a setter:&lt;br /&gt;&lt;pre class="brush:java; first-line:133"&gt;public void setPositionListener(final CustomSliderPositionListener listener) {&lt;br /&gt;    mPositionListener = listener;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And it should be initialised in the constructor, so you should add this line to the end of the constructor:&lt;br /&gt;&lt;pre class="brush:java; first-line:46"&gt;mPositionListener = null;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, the listener should be called if the position does indeed changes, so you will need to add a few lines to &lt;i&gt;setPosition&lt;/i&gt;, inside the if statement just after the call to invalidate:&lt;br /&gt;&lt;pre class="brush:java; first-line:104"&gt;if (mPositionListener != null) {&lt;br /&gt;        mPositionListener.onPositionChange(mPosition);&lt;br /&gt;      }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Ok, done.&lt;br /&gt;(You should really add similar code for getting notified about changes to min and max as well. Feel free to do that, but I will not add it here, for the sake of the size of the tutorial.)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 3.3 Update the activity.&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_3_3&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Again, the activity is there to show you that things are working, so let's do just that.&lt;br /&gt;In you &lt;i&gt;main.xml&lt;/i&gt;, add a text view and a button. The purpose of the text view is to show the current position of the indicator, and the purpose of the button is to reset it to the centre.&lt;br /&gt;Your new &lt;i&gt;main.xml&lt;/i&gt; should look something like this:&lt;br /&gt;&lt;pre class="brush:xml; first-line:1"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;RelativeLayout &lt;br /&gt;    xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;    android:layout_width="fill_parent"&lt;br /&gt;    android:layout_height="fill_parent"&lt;br /&gt;    &amp;gt;&lt;br /&gt;    &amp;lt;com.enea.training.customview.CustomSlider android:id="@+id/slider_horizontal"&lt;br /&gt;      android:layout_height="wrap_content"&lt;br /&gt;      android:layout_width="fill_parent"&lt;br /&gt;      android:layout_alignParentLeft="true"&lt;br /&gt;      android:layout_alignParentTop="true"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;    &amp;lt;Button android:id="@+id/button_reset"&lt;br /&gt;      android:text="@string/reset"&lt;br /&gt;      android:onClick="onReset"&lt;br /&gt;      android:layout_width="wrap_content"&lt;br /&gt;      android:layout_height="wrap_content"&lt;br /&gt;      android:layout_alignParentRight="true"&lt;br /&gt;      android:layout_alignParentBottom="true"&lt;br /&gt;      /&amp;gt;&lt;br /&gt;    &amp;lt;TextView android:id="@+id/values"&lt;br /&gt;      android:layout_width="wrap_content"&lt;br /&gt;      android:layout_height="wrap_content"&lt;br /&gt;      android:layout_alignParentRight="true"&lt;br /&gt;      android:layout_above="@id/button_reset"&lt;br /&gt;      /&amp;gt;&lt;br /&gt;&amp;lt;/RelativeLayout&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice that I have changed the id of the slider, this is a hint of what is to come...&lt;br /&gt;You will also need to add a string for your button. Add this to res/values/strings.xml:&lt;br /&gt;&lt;pre class="brush:xml; first-line:4"&gt;&amp;lt;string name="reset"&amp;gt;Reset&amp;lt;/string&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You will also need to add a fair bit of code to your CustomSliderActivity. First of all you will need two member fields, for the text view and the slider:&lt;br /&gt;&lt;pre class="brush:java; first-line:11"&gt;private TextView     mValueHorizontal;&lt;br /&gt;  private CustomSlider mSliderHorizontal;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You will also need to initialise th fields in onCreate. That includes implementing the &lt;i&gt;onPositionChanged&lt;/i&gt; listener added in step 3.2, and setting min, max and position by calling the setters in step 3.1.&lt;br /&gt;The listener calls to a helper method, &lt;i&gt;displayValues()&lt;/i&gt; that will show the position of the indicator properly formatted in a text view.&lt;br /&gt;Your new &lt;i&gt;onCreate()&lt;/i&gt;, and the helper method, should look like this:&lt;br /&gt;&lt;pre class="brush:xml; first-line:14"&gt;@Override&lt;br /&gt;  public void onCreate(final Bundle savedInstanceState) {&lt;br /&gt;    super.onCreate(savedInstanceState);&lt;br /&gt;    setContentView(R.layout.main);&lt;br /&gt;&lt;br /&gt;    mValues = (TextView) findViewById(R.id.values);&lt;br /&gt;&lt;br /&gt;    mSliderHorizontal = (CustomSlider) findViewById(R.id.slider_horizontal);&lt;br /&gt;    mSliderHorizontal.setPositionListener(new CustomSliderPositionListener() {&lt;br /&gt;      public void onPositionChange(final float newPosition) {&lt;br /&gt;        displayValues();&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    mSliderHorizontal.setMinMax(-100.0f, 100.0f);&lt;br /&gt;    mSliderHorizontal.setPosition(30.0f);&lt;br /&gt;    displayValues();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  void displayValues() {&lt;br /&gt;    final String str = String.format("Horizontal: %3.2f",&lt;br /&gt;        mSliderHorizontal.getPosition());&lt;br /&gt;    mValues.setText(str);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All that is left now is to implement the callback for the button. Upon clicking the button, the indicator should go to the center of the slider. The code should look like this:&lt;br /&gt;&lt;pre class="brush:xml; first-line:39"&gt;public void onReset(final View v) {&lt;br /&gt;    final float min = mSliderHorizontal.getMin();&lt;br /&gt;    final float max = mSliderHorizontal.getMax();&lt;br /&gt;    final float newPos = (max - min) / 2 + min;&lt;br /&gt;    mSliderHorizontal.setPosition(newPos);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Time for another test run of your project. Make sure the code works as expected, and don't forget to click the button.&lt;br /&gt;Modify the hard-coded values in onCreate and verify that the slider reflects your changes.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Step 4 onTouchListener&lt;/h3&gt;&lt;br /&gt;&lt;i&gt;git checkout step_4&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;About time to interact a bit more. This is probably the simplest step of them all. All you need to do is in your constructor tell your view that it should use a touch listener:&lt;br /&gt;&lt;pre class="brush:xml; first-line:48"&gt;setOnTouchListener(new OnTouchListener() {&lt;br /&gt;      public boolean onTouch(final View v, final MotionEvent event) {&lt;br /&gt;        final float pos;&lt;br /&gt;        pos = (mMin + ((mMax - mMin) / (mIndicatorMaxPos - mIndicatorMinPos))&lt;br /&gt;              * event.getX());&lt;br /&gt;        setPosition(pos);&lt;br /&gt;        return true;&lt;br /&gt;      }&lt;br /&gt;    });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Done. Run your project and try to move the indicator with your finger. Hit the reset button to get it back to the center.&lt;br /&gt;&lt;br /&gt;That's it for this part of the article. In the next part, you will see how to make a vertical slider, and how to set some attributes from xml.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html"&gt;Part I - Graphics&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="color: #999999;"&gt;Part II - Interaction&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.androidenea.com/2011/10/creating-custom-view-part-3-xml.html"&gt;Part III - Xml Attributes&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Please use the comments field if you have any questions.&lt;br /&gt;&lt;br /&gt;/Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-4744494746674538981?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/4744494746674538981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/4744494746674538981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/4744494746674538981'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/10/creating-custom-view-part-2-interaction.html' title='Creating a custom view, part 2 - Interaction'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-5113780918222397237</id><published>2011-10-14T10:30:00.001+02:00</published><updated>2011-10-19T13:50:34.431+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NFC QR barcode'/><title type='text'>Using NFC in Android</title><content type='html'>Near Field Communication (NFC) is a technology for data exchange between devices in close proximity. It traces its root back to RFID, where a reader drives a passive electronic tag through a magnetic field. This is a typical use case for NFC, but it can also be used by two active devices to communicate with each other.&lt;br /&gt;&lt;br /&gt;APIs for NFC have now been added to the Android SDK, and a few phones with the NFC capability are available. I have looked into how we could use NFC to improve an existing Android application we develop. The application is targeted for cities, and one of its features is to provide information about various places of public interest, and in some cases allow reports of malfunction to be sent through the application. This feature could make use of NFC by having tags posted at the places of interest, which would allow users to get directly to the information about the place by just tapping the phone on the tag. Another possibility would be to use Peer-to-Peer data exchange to let a user running the application tap another phone. If the other phone has the application installed, it would start the application on the same activity, otherwise the other phone may be redirected to the application on Android Market.&lt;br /&gt;&lt;br /&gt;I looked more closely at the first use case of having tags at places of interest. One initial consideration is that the number of phones with NFC is still very small. It would therefore be desirable to have an alternative way to achieve the same functionality for other phones. For this reason I also had a look at using QR codes, which can be read through the camera in the phone.&lt;br /&gt;&lt;br /&gt;When the Android system detects an NFC device, it searches for the most suitable application to process the data. NFC only works over a very short range, so having the user select the application to use from a list is only used as a last resort, since this would typically cause the user to move the phone away from the device, and thereby break the NFC connection. Instead, the NFC API has defined several types of intents with different priorities, and with different options to filter on tag content or technology. The highest priority is given to the foreground application, which can register itself to intercept any NFC intent. This is not a good option in our application, since it would require the user to start the application before tapping the phone on the tag. &lt;br /&gt;&lt;br /&gt;The next highest priority is applications that filter on tag content, which would work well in this case. The content could be set to anything we want, since the tags would be made specifically for our application. A standard type of content which has support for filtering in Android is URIs. To ensure that our application gets the NFC intent we could use a non-standard scheme. The host part of the URI could be used to select the activity to use within the application, and an identifier could be included as a URI parameter:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;abc://point?id=123&lt;/pre&gt;&lt;br /&gt;The intent filter for these NFC tags would look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;intent-filter&amp;gt;&lt;br /&gt;  &amp;lt;action android:name="android.nfc.action.NDEF_DISCOVERED" /&amp;gt;&lt;br /&gt;  &amp;lt;data android:host="point" android:scheme="abc" /&amp;gt;&lt;br /&gt;  &amp;lt;category android:name="android.intent.category.DEFAULT" /&amp;gt;&lt;br /&gt;&amp;lt;/intent-filter&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The same URI could also be encoded in a QR code. I used a bar code reader called ZXing which can easily be integrated with other applications. It can also do the reverse, i.e. generate a bar code image from text data which is useful for testing. There are two ways to use ZXing to get the scanned QR code into our application:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Our application can send a specific intent defined by ZXing for integration. This starts the ZXing application and a result is returned when the scan is complete (or the scan was cancelled).&lt;/li&gt;&lt;li&gt;The ZXing application is started and a QR code is scanned by the user. When the content is a URI, the user gets an option to open it. Our application can get the intent generated by this option by declaring an intent filter matching the URI.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;For maximum usability, both ways could be implemented, allowing the user to proceed regardless of which application was started first. The way described in 1 above is described on the ZXing web page. The second way, which is what I tried, is quite simple. Our application declares an intent filter, which is very similar to the NFC intent filter above:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;intent-filter&amp;gt;&lt;br /&gt;  &amp;lt;action android:name="android.intent.action.VIEW" /&amp;gt;&lt;br /&gt;  &amp;lt;data android:host="point" android:scheme="abc" /&amp;gt;&lt;br /&gt;  &amp;lt;category android:name="android.intent.category.DEFAULT" /&amp;gt;&lt;br /&gt;&amp;lt;/intent-filter&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The URI can then be retrieved through the getData method on the received intent, in order to extract the id parameter, and this is used to find and display the desired information.&lt;br /&gt;&lt;br /&gt;Some of the NFC features were introduced in API level 9, and the other were introduced in API level 10. The Android SDK develper guide describes how to declare an application to require this API level as well as NFC permission and hardware. This is however not what we want for our application. We want to use NFC if it is available, but the application should install and work without NFC and on old devices at lower API levels. The NFC permission must be declared to get NFC to work when it is available. The platform will use the permission declaration to implicitly derive the NFC hardware requirement, but the application can override this by explicitly declaring that NFC hardware is not required. Finally, the required API level can be kept at a low level while still allowing the application to use the NFC features in API level 10, by using the targetSdkVersion attribute. The result is the following declarations:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;uses-permission android:name="android.permission.NFC" /&amp;gt;&lt;br /&gt;&amp;lt;uses-feature android:name="android.hardware.nfc" android:required="false" /&amp;gt;&lt;br /&gt;&amp;lt;uses-sdk android:minsdkversion="4" android:targetsdkversion="10" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The application can then be compiled with the API level 10 SDK, but can still be installed on anything with API level 4 or higher. In order to make use of NFC, the application will have to use classes in the android.nfc package, which is not available before API level 9. This may cause a&amp;nbsp; VerificationError on the application if it is not handled correctly. The solution is to put all dependencies on NFC into separate application classes that are only loaded on devices that actually support NFC. This works because the Dalvik VM only loads and verifies the application classes the first time any method or member in them are accessed. So even though some application classes would not compile on the API level of the device, the application will still run without errors as long as the classes using a higher API level are not touched. The application can check the API level of the device at runtime through the constant ”Build.VERSION.SDK_INT”. The application can also check if the NFC feature is available through the ”PacketManager.hasSystemFeature” method. Note that this method is only available from API level 5, so the API level must be checked first, and the feature check needs to be in a separate application class that is not loaded on lower API level devices.&lt;br /&gt;&lt;br /&gt;The QR code alternative does not have the same problem with API levels (as the ZXing barcode reader only requires API level 3), but it will obviously only work if the barcode reader is installed. If the integration is implemented by starting the scan from ZXing, which then sends a ”VIEW” intent, then the application is not required to check anything. However in the other integration option, where the application sends an intent to the barcoder reader to initiate the scan, the application must check at runtime if the barcode reader is available. This check can be done with the ”PacketManager.queryIntentActivities” method. When the result of this check is negative, the application could disable any ”scan” button or anything else in the user interface used to initiate a scan operation. The application could also provide a link to the barcode reader in Android market to make it easy for the user to enable the QR code scanning feature. The link could be made like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;Intent intent = new Intent(Intent.ACTION_VIEW);&lt;br /&gt;intent.setData(Uri.parse("market://search?q=pname:com.google.zxing.client.android"));&lt;br /&gt;startActivity(intent);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In summary, I found that the NFC capability could indeed be used to add a new feature to our application. It would make the application easier to use, and it could be implemented without limiting the availablility of the application to phones that have NFC hardware. If QR codes are used as a complement to NFC tags, then the same functionality could be implemented for phones without NFC.&lt;br /&gt;&lt;br /&gt;/Mikael&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-5113780918222397237?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/5113780918222397237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/10/using-nfc-in-android.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5113780918222397237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5113780918222397237'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/10/using-nfc-in-android.html' title='Using NFC in Android'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-6279150602086673251</id><published>2011-09-05T12:02:00.000+02:00</published><updated>2011-09-05T12:02:58.126+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='seminar'/><category scheme='http://www.blogger.com/atom/ns#' term='presentations'/><category scheme='http://www.blogger.com/atom/ns#' term='industrial'/><category scheme='http://www.blogger.com/atom/ns#' term='automation'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Using Android in industrial applications</title><content type='html'>Enea will be represented at the SICS (Swedish Institute for Computer Science) Android theme day about Android beyond phones and tablets.&lt;br /&gt;Our Android expert Robert Niemi will do a speach titled "Android in industrial applications - today and tomorrow."&lt;br /&gt;&lt;br /&gt;The day will be filled with interesting seminars, followed by a panel discussion.                     &lt;br /&gt;&lt;br /&gt;The theme day is in Stockholm, Sweden on Sept. 21. Please follow this link for more information: &lt;a href="http://www.sics.se/androiddagen2011"&gt;http://www.sics.se/androiddagen2011&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;/Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-6279150602086673251?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/6279150602086673251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/09/using-android-in-industrial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6279150602086673251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6279150602086673251'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/09/using-android-in-industrial.html' title='Using Android in industrial applications'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-283498674396395755</id><published>2011-08-30T13:54:00.000+02:00</published><updated>2011-08-30T13:54:41.687+02:00</updated><title type='text'>An example of porting existing code to a custom Android device</title><content type='html'>It is due time for another technical post here on the blog. This post will be about porting existing c-libraries to Android, something I did as part of the dev board demos we are doing here at Enea.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Platform addition or NDK&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are two ways of bringing native code to an Android device, either add it to the platform itself and integrate it with the framework, or include it with an application package. The latter method have evolved a lot and with the release of NDK version 5 even allows you to hook directly into the application lifecycle http://developer.android.com/reference/android/app/NativeActivity.html from the NDK. The NDK is useful for any application where you have need of native performance, have portable C libriaries you want to reuse or just some legacy native code that could be included in your application. The NDK integrates well with the Android SDK and is a great way to include native functionality in your application. It should be the preferred way for any application that needs to be reusable across a lot of Android devices.&lt;br /&gt;&lt;br /&gt;The other option is to include your functionality, it may be native or Java, as an API extension for all applications to use. This will only work on devices that implement these extensions and it may be a suitable option for device builders. This is the variant that we aim for here.&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Analyze the existing project&lt;/span&gt; &lt;br /&gt;Porting native code to Android is not always straight forward, especially if we are talking about C++ code due to the fact that Android uses its own c-runtime with limited support for exceptions among other things. If you want to know more about the details of bionic there is an overview in the NDK docs.&lt;br /&gt;&lt;br /&gt;The code I wanted to port for this project was the &lt;a href="http://sourceforge.net/projects/linx/%20"&gt;Enea LINX for Linux &lt;/a&gt; framework which is a fast IPC framework. My purpose was to be able to interact with control systems running our OSE real time operating system which also implements this kind of IPC. LINX consists of a couple of kernel driver modules, a user space library and some configuration and control utilities. It is written in C. I had created a small demo with LINX in Android before where I compiled it separately and used static linking but for this project I wanted a complete port to the Android build system. It did not have any issues with bionic compatability so the port should be straight forward.&lt;br /&gt;&lt;br /&gt;I just want to add a short disclaimer about LINX. I use it here since it is a good example of integrating a solution into Android from kernel drivers up to the API levels. This particular piece of code does add additional IPC mechanisms to the systems which more or less messes up the security model so do not use it unless you are aware of the implications. The steps needed to port code to Android described in this post are however applicable for any type of driver/framework/library that you may want to include on your product.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Adding kernel driver modules &lt;/span&gt;&lt;br /&gt;The first step was to add the kernel modules to the Android build. One way would have built a new kernel and include them directly but for this project I chose to keep them as separate modules. Building for the kernel is not handled by the Android build system meaning that we build them as we would do with any Linux system. The target is an Atmel based development board and in the LINX module build I provide the headers and cross compilation toolchain for that kernel and architecture. &lt;br /&gt;&lt;br /&gt;Now for the Android specific parts. We need to add the compiled kernel modules to the platform build system in some way and create an Android.mk file that includes them in the system image when we build. Add a folder in the source tree where your project will go, device or external are suitable candidates. I created a folder called linx that will hold the entire linx port and in that I added a subfolder called modules where I place the prebuilt kernel modules. Now what we need is an Android makefile to copy them to the suitable place in the out folder for system image generation. This will look like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;LOCAL_PATH := $(my-dir)&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE := linx.ko&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE_CLASS := SHARED_LIBRARY&lt;br /&gt;&lt;br /&gt;# This will copy the file in /system/lib/modules&lt;br /&gt;#&lt;br /&gt;LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/modules&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES := $(LOCAL_MODULE)&lt;br /&gt;&lt;br /&gt;include $(BUILD_PREBUILT)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The standard location for modules on the Android system image is System/lib/modules so that is where we copy them. If we build the platform now the build system will copy our precompiled module linx.ko to the system image that we use for our device. The next step is to make sure that we have the module installed on the system when we run it. This can either be done manually via the shell or via a script that we run during init.&lt;br /&gt;&lt;br /&gt;In this case I have created a shell script to be launched from init.rc with the following content:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;#linx init&lt;br /&gt;insmod /lib/modules/linx.ko&lt;br /&gt;insmod /lib/modules/linx_tcp_cm.ko&lt;br /&gt;netcfg eth0 up&lt;br /&gt;ifconfig eth0 192.168.1.12&lt;br /&gt;mktcpcon --ipaddr=192.168.1.21 ControlConn&lt;br /&gt;mklink --connection=tcpcm/ControlConn control_link&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This includes installing the modules and configuring the network and LINX-link. We launched this from init.rc by adding:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;#linx init script&lt;br /&gt;service linx-setup /system/etc/linx_setup.sh&lt;br /&gt;oneshot&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The setup script is added to the system image in the same way by including it as a prebuilt target.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;LOCAL_PATH := $(my-dir)&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE := linx_setup.sh&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE_CLASS := ETC&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE_PATH := $(TARGET_OUT)/etc&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES := $(LOCAL_MODULE)&lt;br /&gt;&lt;br /&gt;include $(BUILD_PREBUILT)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Creating Android make files for the user space code&lt;/span&gt;&lt;br /&gt;Now that we have the drivers in place the next step is to look at porting the user space libraries. The default LINX build system uses standard GNU make files but we need to create new ones adapted to the Android build system. Start out by adding the source files needed to the linx directory created in the Android source tree. This gives the following structure:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Android.mk  &lt;br /&gt;include  &lt;br /&gt;liblinx  &lt;br /&gt;linx_basic  &lt;br /&gt;linxcfg  &lt;br /&gt;linx_setup.sh  &lt;br /&gt;modules&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I have the linx setup script and the main Android.mk file in the top directory and then we have the source files in separate folders and the include files in the include folder. To illustrate how the Android make files for each source component is created we can use liblinx as an example. The Android.mk file looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;LOCAL_PATH := $(call my-dir)&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES := linx.c&lt;br /&gt;LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include&lt;br /&gt;LOCAL_MODULE := liblinx&lt;br /&gt;LOCAL_PRELINK_MODULE := false&lt;br /&gt;include $(BUILD_SHARED_LIBRARY)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We set our sources by specifying LOCAL_SRC_FILES and the name of the library by specifying LOCAL_MODULE. We also need to supply the header files in the include directory by specifying LOCAL_C_INCLUDES. Finally this is a shared library that we are porting so use the BUILD_SHARED_LIBRARY template. This will build the library with the Android build system and add it to the system image as a shared library with the name liblinx.so.&lt;br /&gt;&lt;br /&gt;The rest of the code is moved to the Android build system in the same way, by creating Android.mk files and specifying type and any dependencies. As another example we may look at the syntax for building the mktcpcon configuration program. This depends on the library we just created and hence the makefile looks entry looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;LOCAL_SRC_FILES := mktcpcon.c&lt;br /&gt;LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include&lt;br /&gt;LOCAL_STATIC_LIBRARIES += liblinxcfg&lt;br /&gt;LOCAL_SHARED_LIBRARIES += liblinx&lt;br /&gt;LOCAL_MODULE := mktcpcon&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here we use the BUILD_EXECUTABLE template and we also need to specify static and shared libraries that we link against.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Summary&lt;/span&gt;&lt;br /&gt;I hope that provides some insight in how you setup the build for an existing linux project to run on an Android system. The steps to follow are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Build any kernel related things using the correct kernel build system and config for your device&lt;/li&gt;&lt;li&gt;Add the kernel modules (and/or kernel) to the platform build system and create Android.mk files for them using the prebuilt template.&lt;/li&gt;&lt;li&gt;Create config and intialization services for your drivers if needed and add them to init.&lt;/li&gt;&lt;li&gt;Move the rest of your code (user space) to the Android source tree and create Android.mk files for them.&lt;/li&gt;&lt;li&gt;If you encounter build errors work them out in the source code and see what incompatabilities your code have with the specifics of the Android C-runtime.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;That wraps up my post for today. Having done this we are now able to use our added drivers and API:s from native programs running in the shell. The next step is to create a JNI layer and java library to allow regular Android applications to make use of our platform additions.&lt;br /&gt;&lt;br /&gt;I have been away for half a year on paternal leave (nice &lt;a href="http://en.wikipedia.org/wiki/Parental_leave#Benefits_in_a_selection_of_countries"&gt;Swedish benefit&lt;/a&gt;) but now it is full time Android hacking again and pushing the team to publish things. Hopefully you will see more activity here including a follow up on this post discussing applications APIs.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-283498674396395755?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/283498674396395755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/08/example-of-porting-existing-code-to.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/283498674396395755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/283498674396395755'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/08/example-of-porting-existing-code-to.html' title='An example of porting existing code to a custom Android device'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-1701360604999242318</id><published>2011-05-05T20:53:00.000+02:00</published><updated>2011-05-05T20:53:12.670+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='seminar'/><category scheme='http://www.blogger.com/atom/ns#' term='presentations'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Android Only</title><content type='html'>Don’t miss the Android Only Conference in Malmö, Sweden in June, the dates are 13 – 14 June 2011.&lt;br /&gt;&lt;br /&gt;The focus will primarily be on Programming and development of Android applications and services. Presentations will also cover design and user interaction, and utilities and services for the developer as well as the end-user of Android devices. Check out the details on &lt;a href="http://swdc-central.com/androidonly2011malmo/"&gt;http://swdc-central.com/androidonly2011malmo/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Enea is a Silver Sponsor for this event and our expert Mattias Björnheden will give a presentation with the title:&lt;br /&gt;&lt;br /&gt;“Create your own Android device—working with Android on development boards”&lt;br /&gt;&lt;br /&gt;We will run two of our popular Android trainings at the Android Competence Center in Lund (located 18 km from Malmö) in connection with the event:&lt;br /&gt;&lt;br /&gt;15 – 17 June: “Android Platform for System Engineers”&lt;br /&gt;&lt;br /&gt;20 June: “Android Advanced”&lt;br /&gt;&lt;br /&gt;We will host a competition at the show, where you can win a seat at these trainings!&lt;br /&gt;&lt;br /&gt;See you there!&lt;br /&gt;&lt;br /&gt;Erik&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-1701360604999242318?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/1701360604999242318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2011/05/android-only.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1701360604999242318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1701360604999242318'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2011/05/android-only.html' title='Android Only'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-4670307379146277443</id><published>2010-10-26T16:05:00.001+02:00</published><updated>2010-10-26T20:59:45.031+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='atmel'/><category scheme='http://www.blogger.com/atom/ns#' term='development boards'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='beagleboard'/><title type='text'>Working with Android on development boards</title><content type='html'>This will be the first of a set of post on a project we are doing where we will use an Android powered dev board to provide UI and user control features for an embedded system. I will get back to the setup in later posts but in brief it will consist of two boards, one running a traditional control system and one running a slightly adapted Android platform with extra API:s to interact with the control system. This part focuses on working with Android on dev boards in general and discusses a couple of boards in particular.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_fcXaF6gx74U/TMbbbGCBOcI/AAAAAAAAAEI/7Yd-HprGhdQ/s1600/intro_image.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/_fcXaF6gx74U/TMbbbGCBOcI/AAAAAAAAAEI/7Yd-HprGhdQ/s400/intro_image.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;For platform level hacking the open source project provides a good start with the emulator and that is useful for things like working with the base applications and examining the framework. The emulator is however limited and for a lot of platform level work real hardware is the best way to go. For real hardware there are two routes, either use an existing phone or use some kind of development board. Existing phones are fun platforms for tinkering and enabling features in the way they to it at xda-developers and other forums. As a general lab environment they are limited since they often have very few hardware interfaces exposed and they are often locked down in ways that make interacting with them difficult.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Development boards on the other hand are often made especially for trying out new designs, connecting hardware and having easy debug access. These are often the best platform for working with low level stuff on Android. In fact most phone manufacturers start out with some kind of platform dev board to facilitate early development before they wrap everything in great looking metal and plastic.&lt;br /&gt;&lt;br /&gt;So let us look at working with Android on embedded development boards. First you should decide on why you want to go this route. Dev boards are excellent for:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Low level work on the Android open source project, testing and debugging hardware interaction etc.&lt;/li&gt;&lt;li&gt;Hobby projects where you want to design a great Android based interface for your home-made toaster and need to hook up the android system to some outside electronics.&lt;/li&gt;&lt;li&gt;Professional projects where you are considering building an Android based product, be it a phone, a tablet, music player etc.&lt;/li&gt;&lt;li&gt;Anyone else who wants to explore the full capabilities of Android and understand the platform without the limitations of the emulator or set hardware design of a phone.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Dev boards are probably not the way to go for:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Getting a basic understanding of how to build and run the Android source code. The open source project and the emulator are more than sufficient for that.&lt;/li&gt;&lt;li&gt;Application development work. The SDK and existing phones are perfect for that and saves you a lot of hassle with jumpers, adb bridging and so on.&lt;/li&gt;&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Factors to consider&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now let us say that you are still interested in working with Android on a development board. Then we get to the interesting part on deciding on which one to get. Here I would say there are a few important factors to consider:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Purpose - what to you plan to do with the board&lt;/li&gt;&lt;li&gt;Price&lt;/li&gt;&lt;li&gt;Performance&lt;/li&gt;&lt;li&gt;Existing Android ports for the board&lt;/li&gt;&lt;li&gt;Community&lt;/li&gt;&lt;li&gt;Debugging utilities&lt;/li&gt;&lt;li&gt;Expansion possibilities&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;All of these are important but do not underestimate the power of having an active community around your platform that can help you out if you run into problems. Start by looking at the above factors and note down your requirements in each aspect. And do not forget to take into account other things that I have left out in this bullet list. Once you have some idea of what you need we can start looking at what is available. And that is becoming quite a lot.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Let me start by grouping the different boards into a few categories. And here I will add in a limitation. I will mostly consider ARM-based dev boards since this is the architecture with the widest Android adoption so far and almost all commercial devices shipped so far are based on ARM. That said there is a very active community around Android on &lt;a href="http://www.android-x86.org/"&gt;x86&lt;/a&gt;&amp;nbsp;and also &lt;a href="http://www.mipsandroid.org/"&gt;MIPS&lt;/a&gt; ports. And probably a few more. The most prominent feature of any dev board is the applications processor and system on chip design that will run the actual Android system. Based on that I will use the following categories for ARM based designs:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;State of the art - these are dev boards with high performance system on chips that are often prototypes of platforms that are not even available in commercial products yet.&lt;/li&gt;&lt;li&gt;High end, these are dev boards with an applications processor that matches the high end Android phones that are available today.&lt;/li&gt;&lt;li&gt;Mid and low end - these are either boards with performance that matches early or low end Android phones.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;State of the art development boards&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These platforms are based &amp;nbsp;on dual-core Arm Cortex A9, 1 GHz plus, system on chips with graphics acceleration and other features. In this category I am only aware of a couple of platforms that can be obtained as development boards for general purposes. Two are based on the TI Omap 4 system on chip and can be ordered either as the cheap &lt;a href="http://www.pandaboard.org/"&gt;panda board&lt;/a&gt;&amp;nbsp;or as the more full featured &lt;a href="http://focus.ti.com/general/docs/wtbu/wtbugencontent.tsp?templateId=6123&amp;amp;navigationId=12013&amp;amp;contentId=4578"&gt;Blaze&lt;/a&gt; kit which include touch screens and keyboard. If you are based in North America it is also possible to get the &lt;a href="http://developer.nvidia.com/tegra/tegra-devkit-features"&gt;Tegra 250 dev kit&lt;/a&gt; from Nvidia with similar specs. These boards are interesting since they have more processing power available than anything else on the market but they are also fairly new designs with limited community track record. They may be perfect for experienced embedded hobbyists that want to build a HTPC setup or similar. If you have very little experience working with embedded development it may be better to start out with something with a longer track record and more information available on forums, blogs and wikis. For professionals you need to consider if you really need this kind of processing power in your design. Maybe advanced 3D graphics and full HD video is not part of your use case and then maybe these types of platforms will eat more power and cause more issues with advanced features than they provide&amp;nbsp;benefits.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt; High end development boards.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These are ARM Cortex A8 based designs similar to what is powering most of the high end Android smarthphones that are available today. In this category we have a number of SoC and a large amount of development boards based on these SoCs. To mention a few of the families we have the&amp;nbsp;&lt;a href="http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=i.MX515"&gt;Freescale i.Mx 515&lt;/a&gt;, evolution dev kit and android tool and the&amp;nbsp;Texas Instruments &lt;a href="http://focus.ti.com/general/docs/wtbu/wtbuproductcontent.tsp?templateId=6123&amp;amp;navigationId=11989&amp;amp;contentId=4682"&gt;OMAP3&lt;/a&gt;, most notable the Beagle board and the Zoom II dev kit.&amp;nbsp;Since these run on the same CPU family (ARM Cortex A8) as most of the commercially available Android phones do and have been around for a while they are often well tested and relatively stable. This is especially true of the Omap based Beagle board which features a large developer community. The Omap on the Beagle board is also very similar to the Omap that powers the popular Motorola Droid phone. There are a number of derivatives from the Beagle with more peripherals and expansion possibilities.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-size: x-large;"&gt;&lt;/div&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt; Mid and low end development boards&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a more unexplored area but with some interesting products. Android this far has been a lot about performance and most community boards have been higher end boards but as interest for using Android outside the smartphone space is increasing so is the number of low cost platforms with support for the system. These boards are generally based on ARM926 or ARM11 CPUs and have a limited set of accellerators and peripherals. Many dev boards in this category have too little memory to run Android (128 MB RAM is some kind of current minimum but more is even better). There are some Samsung boards, something from &lt;a href="http://www2.renesas.com/mobile/en/emma_mobile/hdk_sdk/index.html"&gt;Renesas&lt;/a&gt; and once again probably a lot of others. The board that we have worked with in this category is from Atmel, the AT91SAM9M10-EKES borad. While their Android community is relatively young compared to the Beagle board Atmel has a tradition of having a thriving &lt;a href="http://www.at91.com/"&gt;community&lt;/a&gt;&amp;nbsp;around their at91 platforms in general.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Some practical details&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that we are finally past the overview we can get to the practical details on working with development boards. If you are considering to get a develoment board for Android I would suggest that  you try to download and build whatever Android distribution is availble for that board before you get the hardware. The state of the distribution will tell you a lot about how hard it will be to get the hardware working later on. If there is no Android distribution available for your hardware make sure that you are aware what the &lt;a href="http://source.android.com/porting"&gt;porting&lt;/a&gt; effort will be and also analyze that the hardware will even be capable of running Android in terms of performance and memory available.&lt;br /&gt;&lt;br /&gt;Another thing to investigate is how you will boot and run Android on the dev board. Does it contain a NAND flash or SD card interface. Is it possible to set up a network file system and boot Android from that? Having working adb tools are also very nice when working on a dev board. It is much more convenient to update just your shared library through an adb sync instead of having to build, generate a system image and flash it to the board every time you need to test an update.&lt;br /&gt;Regardless of what board you choose prepare to spend some time understanding how to boot it up with your Android build. Often they are delivered with some other software as default configuration. Prepare to spend a few hours up to a few days just to get familiar with boot and flash options. How to set the jumpers in the correct state to be able reflash the board etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;Our experience&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These are some impressions for three of the different boards that we have worked with so far.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://beagleboard.org/"&gt;&lt;b&gt;Beagle board&lt;/b&gt;&lt;/a&gt;:&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_fcXaF6gx74U/TMbcjVf6m8I/AAAAAAAAAEU/oq9xIe0PYYQ/s1600/beagle_board.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="253" src="http://3.bp.blogspot.com/_fcXaF6gx74U/TMbcjVf6m8I/AAAAAAAAAEU/oq9xIe0PYYQ/s400/beagle_board.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;BeagleBoard in action&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;i&gt;Pros:&lt;/i&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Very powerful board for the price tag.&lt;/li&gt;&lt;li&gt;Good community around Android and the Rowboat distribution on TI Omap&lt;/li&gt;&lt;li&gt;Well tested CPU for Android, very similar to the SoC powering the Motorola Droid and other devices&lt;/li&gt;&lt;li&gt;A lot of other Linux work happening on the Omap platform such as MeeGo&lt;/li&gt;&lt;li&gt;Decent debug support&lt;/li&gt;&lt;li&gt;Relatively easy to get started  with and several boot options&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Cons:&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;No ethernet support in default configuration, has to be added via USB.&lt;/li&gt;&lt;li&gt;No touch screen or other peripherals included, not even power adapter&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Summary:&lt;/i&gt;&lt;br /&gt;The Beagle board is a very powerful board for the price ($149) and if you connect to a regular monitor and keyboard it is a very capable development platform for low level work. We have run a number of projects on this platform ranging from initial demos and driver projects to advanced research stuff. The limitations made to keep the price down are a bit annoying and nowadays I would recommend getting the updated &lt;a href="http://beagleboard.org/hardware-xM"&gt;BeagleBoard xM&lt;/a&gt;&amp;nbsp;version instead. That will add an ethernet port and more USB ports. There are also versions and derivatives that include screens etc.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://focus.ti.com/general/docs/wtbu/wtbugencontent.tsp?templateId=6123&amp;amp;navigationId=12013&amp;amp;contentId=53575&amp;amp;DCMP=wtbu_zoom&amp;amp;HQS=Other+PR+zoom2_technical"&gt;&lt;b&gt;Zoom II&lt;/b&gt;&lt;/a&gt;&lt;b&gt;:&lt;/b&gt;&lt;br /&gt;This is another OMAP based device but includes and the SoC is very similar to the BeagleBoard but it is packaged more like a real device with touch screen and keyboard.&lt;br /&gt;&lt;i&gt;Pros:&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Much more peripherals included compared to the Beagle&lt;/li&gt;&lt;li&gt;Portable device like package, good for demos&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Cons:&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;More expensive than the Beagle&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Summary:&lt;/i&gt;&lt;br /&gt;This device is very similar to the Beagle board and shares the same attributes beyond the two things mentioned here.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.atmel.com/products/at91/sam9m10.asp?family_id=605"&gt;&lt;b&gt;Atmel AT91SAM9M10-EKES&lt;/b&gt;&lt;/a&gt;&lt;b&gt;:&lt;/b&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_fcXaF6gx74U/TMbbvpxbghI/AAAAAAAAAEQ/kBgC87pfFho/s1600/atmel_board.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="300" src="http://4.bp.blogspot.com/_fcXaF6gx74U/TMbbvpxbghI/AAAAAAAAAEQ/kBgC87pfFho/s400/atmel_board.jpg" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;An Atmel boad with Android up and running&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;i&gt;Pros:&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Includes touch screen directly on the board&lt;/li&gt;&lt;li&gt;Connection cables and power supply included&lt;/li&gt;&lt;li&gt;Good community around the at91 boards in general, emerging Android community&lt;/li&gt;&lt;li&gt;Based on relatively small and low cost ARM926 CPU&lt;/li&gt;&lt;li&gt;Good value for money for a relatively complete kit&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Cons:&lt;/i&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dev tools seem a bit Windows focused, it was a little bit tricky to get started from a Linux dev machine&lt;/li&gt;&lt;li&gt;Android support is relatively new for this platform, not as well tested as the Omap distributions&lt;/li&gt;&lt;/ul&gt;&lt;i&gt;Summary:&lt;/i&gt;&lt;br /&gt;I think this is a really interesting dev kit. Especially when looking at developing things that do not have the high-end smartphone level of performance requirements. Since it includes a screen and decent amount of connections it can be used as a compact demo board. We got this relatively recently and will probably base our next demo on it. After some initial hickups with the tools it is straight forward to develop on and the support from Atmel and the community seems to be growing rapidly. We still need to do some benchmarking though and see how it handles Android compared to higher end alternatives.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope this article provides some insight on working with Android on development boards. With the amount of Android related news currently I am sure I have missed some capable platforms. Feel free to add whatever platform you are familiar with in the comments and I will update this post with more info. Once again I would like to remind you that I have skipped entire architectures such as x86, MIPS and PowerPC in this article.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;/div&gt;&lt;div style="font-size: x-large;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-4670307379146277443?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/4670307379146277443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/10/working-with-android-on-development.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/4670307379146277443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/4670307379146277443'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/10/working-with-android-on-development.html' title='Working with Android on development boards'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_fcXaF6gx74U/TMbbbGCBOcI/AAAAAAAAAEI/7Yd-HprGhdQ/s72-c/intro_image.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-840908705635693343</id><published>2010-10-04T15:53:00.000+02:00</published><updated>2010-10-04T15:53:19.538+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='presentations'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Slides from the presentation on Security Concepts at Android Only</title><content type='html'>The slides from my presentation on Android Security Concepts held at the Android Only conference in Stockholm on September are now available. The video from the presentation will be available on the &lt;a href="http://swdc-central.com/androidonly/index.html"&gt;conference homepage&lt;/a&gt; in a couple of weeks.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="https://docs.google.com/present/embed?id=dd6r2nrx_4fqtwzqfc" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-840908705635693343?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/840908705635693343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/10/slides-from-presentation-on-security.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/840908705635693343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/840908705635693343'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/10/slides-from-presentation-on-security.html' title='Slides from the presentation on Security Concepts at Android Only'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-967682233704004100</id><published>2010-09-17T10:59:00.000+02:00</published><updated>2010-09-17T10:59:29.098+02:00</updated><title type='text'>Android Only conference and plans for the fall</title><content type='html'>Once again it has been low activity here during the summer months but hopefully we will get back up to 1-2 posts a month from now on. We are currently working on a demo system that combine an Android CPU for user interaction with a control system running on a separate CPU and we hope to describe the steps in some detail.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Android only&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I will give a presentation on Android security concepts at the &lt;a href="http://swdc-central.com/androidonly/index.html"&gt;Android Only conference&lt;/a&gt; in Stockholm, Sweden, on September 29-30. Looks like it could be a really cool conference. Interesting speakers and hopefully a lot of new Android devices to check out. Follow the link for more details.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;New hardware on the horizon&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you are looking for a technical post and can't wait a few more days I wrote a piece on the ARM Cortex A15 launch on the Enea corporate blog. Not directly Android but definitely mobile computing related. You can find that post here: &lt;a href="http://blog.enea.com/Blog/bid/51605/ARM-Cortex-A15-What-Multicore-Developers-Need-to-Know"&gt;http://blog.enea.com/Blog/bid/51605/ARM-Cortex-A15-What-Multicore-Developers-Need-to-Know&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-967682233704004100?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/967682233704004100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/09/android-only-conference-and-plans-for.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/967682233704004100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/967682233704004100'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/09/android-only-conference-and-plans-for.html' title='Android Only conference and plans for the fall'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-57909843924138390</id><published>2010-06-24T13:18:00.000+02:00</published><updated>2010-06-24T13:18:33.798+02:00</updated><title type='text'>Sky Is The Limit - Now on Android Market</title><content type='html'>Finally we're releasing our first app on Android Market. The app is actually a new type of game that is&amp;nbsp;using the accelerometer in an exiting way. The game is really easy, all you have to do is to throw your phone up in the air as high as you dare. As mentioned we're using the accelerometer and also some secret algorithms to calculate how high a user can throw. We are also using an SQLLite database to store the highscores on the phone and a server with a SQL database to store global highscores.&lt;br /&gt;&lt;br /&gt;During development we accidently crashed the sensors on one phone, but considering how many throws we've done, that's ok. Included in the game is four different highscores, Phone, National, Global and also a global hisghscore based on your phone model. &lt;br /&gt;Right now the Android Team record is 8.5m high! Do you dare try to beat us?!&lt;br /&gt;The name of the game is SkyIsTheLimit and can be downloaded on android market. Search for "skyisthelimit".&amp;nbsp;Or use the QR code with a barscanner:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_fcXaF6gx74U/TCM8uJhaA9I/AAAAAAAAADg/qIEQbCdbJDs/s1600/CR-Code.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/_fcXaF6gx74U/TCM8uJhaA9I/AAAAAAAAADg/qIEQbCdbJDs/s200/CR-Code.png" width="192" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some screenshots:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_fcXaF6gx74U/TCM9Smh4E5I/AAAAAAAAADo/EC01Auq1KZM/s1600/globalHighscore.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_fcXaF6gx74U/TCM9Smh4E5I/AAAAAAAAADo/EC01Auq1KZM/s320/globalHighscore.png" width="212" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_fcXaF6gx74U/TCM9eMp4L5I/AAAAAAAAADw/wDHJVHtnrvs/s1600/grandma.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_fcXaF6gx74U/TCM9eMp4L5I/AAAAAAAAADw/wDHJVHtnrvs/s320/grandma.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/Henrik and Tommy&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-57909843924138390?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/57909843924138390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/06/sky-is-limit-now-on-android-market.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/57909843924138390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/57909843924138390'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/06/sky-is-limit-now-on-android-market.html' title='Sky Is The Limit - Now on Android Market'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_fcXaF6gx74U/TCM8uJhaA9I/AAAAAAAAADg/qIEQbCdbJDs/s72-c/CR-Code.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3352856923223943895</id><published>2010-06-21T17:10:00.000+02:00</published><updated>2010-06-21T17:10:06.227+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='repo'/><category scheme='http://www.blogger.com/atom/ns#' term='manifest'/><title type='text'>Using the local_manifest.xml file in repo to customize your Android project setup</title><content type='html'>This post will discuss how to use repo and the local_manifest.xml file to keep track of projects that are not part of the default manifest for the Android open source project. This can be used to keep track of some projects that are maintained by the Android team but are not included in the default distribution. It can also be used to include other git-based projects within your android platform source tree. Adding a local manifest file is a good way to set up a personalized environment to work with Android for hacking or in a small team. Any additions to Android can be kept in separate git repositories and tracked using the local manifest. For commercial level projects it may be better to run your own repo server and edit the manifest directly to make sure that it is version controlled and that all developers see the same projects. We may get back to that topic in a separate blog post.&lt;br /&gt;&lt;br /&gt;Now let's take a look at the practical details. The format of the local manifest file follows the standard manifest format described in the manifest-format.txt file under .repo/repo/docs in the Android Open Source project. To create a local manifest add a file with the name local_manifest.xml and place it directly in the .repo folder of your Android Open Source Project.  It will be parsed by repo as part of a normal repo sync.&lt;br /&gt;&lt;br /&gt;I keep a project on machine to track the latest development in the Android platform. It is setup to track the current master branch in the default configuration. Since I often work with hardware as well I am also interested in developments in the kernel. Currently there are a number of different kernel trees being run as part of android. None of them are part of the default manifest. In my setup I want to track the common kernel but also see what is going on with hardware support for Qualcomm (msm) and TI (omap)  platforms. These are all maintained by the android team and I can use the default remote site to get them. I need however to inform repo about what branch I want to track by adding the revision tag. For each project add a tag like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;project path=&amp;quot;kernel&amp;quot;&lt;br /&gt;      name=&amp;quot;kernel/common&amp;quot;&lt;br /&gt;      remote=&amp;quot;korg&amp;quot;&lt;br /&gt;      revision=&amp;quot;android-goldfish-2.6.29&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Another thing I also find myself using is Busybox and since I set it up the build config and do some adaptations when using it with Android I like to track the source for that as well within my Android tree. This can easily be achieved in the local manifest by adding a new remote site for Busybox and then adding the project itself like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;remote  name=&amp;quot;busybox&amp;quot;&lt;br /&gt;           fetch=&amp;quot;git://git.busybox.net/&amp;quot;/&amp;gt;&lt;br /&gt;&amp;lt;project path=&amp;quot;busybox&amp;quot;&lt;br /&gt;      name=&amp;quot;busybox&amp;quot;&lt;br /&gt;             remote=&amp;quot;busybox&amp;quot;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;To sum things up this means that each time I do a repo sync I will get the latest version of the Android Open source project and also updated repositories for the three different kernel trees that I track and an updated busybox source. All in all my local_manifest file looks like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;  &amp;lt;manifest&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;remote  name=&amp;quot;busybox&amp;quot;&lt;br /&gt;           fetch=&amp;quot;git://git.busybox.net/&amp;quot;/&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;project path=&amp;quot;kernel&amp;quot;&lt;br /&gt;      name=&amp;quot;kernel/common&amp;quot;&lt;br /&gt;      remote=&amp;quot;korg&amp;quot;&lt;br /&gt;      revision=&amp;quot;android-goldfish-2.6.29&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;project path=&amp;quot;kernel_msm&amp;quot;&lt;br /&gt;      name=&amp;quot;kernel/msm&amp;quot;&lt;br /&gt;      remote=&amp;quot;korg&amp;quot;&lt;br /&gt;             revision=&amp;quot;android-msm-2.6.32&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;project path=&amp;quot;kernel_omap&amp;quot;&lt;br /&gt;      name=&amp;quot;kernel/omap&amp;quot;&lt;br /&gt;      remote=&amp;quot;korg&amp;quot;&lt;br /&gt;             revision=&amp;quot;android-omap-2.6.32&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;project path=&amp;quot;busybox&amp;quot;&lt;br /&gt;      name=&amp;quot;busybox&amp;quot;&lt;br /&gt;             remote=&amp;quot;busybox&amp;quot;/&amp;gt;&lt;br /&gt;  &amp;lt;/manifest&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3352856923223943895?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3352856923223943895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/06/using-localmanifestxml-file-in-repo-to.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3352856923223943895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3352856923223943895'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/06/using-localmanifestxml-file-in-repo-to.html' title='Using the local_manifest.xml file in repo to customize your Android project setup'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-8304760030558699738</id><published>2010-05-10T09:16:00.000+02:00</published><updated>2010-05-10T09:16:45.493+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><category scheme='http://www.blogger.com/atom/ns#' term='native'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='repo'/><category scheme='http://www.blogger.com/atom/ns#' term='workflow'/><title type='text'>Android Open Source Project workflow</title><content type='html'>&lt;span style="font-size: small;"&gt;Thought I should share a couple of flowcharts showing how to do basic work with the platform source code. In this case we assume that there is a platform library that need some adaptations.&lt;/span&gt; It is impossible to cover all the steps in an overview like this but look at is as a basic guide if you have limited experience of the platform source. I have divided the guide into two different images. The first one shows the practical work itself (i.e. the "happy hacking") while the second one illustrates the steps needed to handle the change in an environment using repo and gerrit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Part 1 - code changes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;This part assumes you are working with the Android open source project for a device or some other project and have some changes that need to be made to a platform module.&lt;/span&gt;&lt;/span&gt; The utility commands described here all come from the envsetup script. There is a lot more to say about things like testing depending on your general setup but I hope this provides an illustration on how to go about making a small change in the Android platform and trying it out.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_fcXaF6gx74U/S-bUr2q2qPI/AAAAAAAAADQ/lUZ77NPCN7E/s1600/Android_update_workflow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/_fcXaF6gx74U/S-bUr2q2qPI/AAAAAAAAADQ/lUZ77NPCN7E/s640/Android_update_workflow.png" width="456" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Part 2 - commit and review&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;Making a change is all good if you are just trying things out. In a real project however you are probably working with a setup using repo and gerrit for your project and would like to submit your changes. This flowchart provides additional details on the repo and git commands needed to go along with a change as described in part 1.&lt;/span&gt;&amp;nbsp;&lt;/span&gt; &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_fcXaF6gx74U/S-bUur6ZcAI/AAAAAAAAADY/eNe7tDcf1JQ/s1600/Android_update_repo_flow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/_fcXaF6gx74U/S-bUur6ZcAI/AAAAAAAAADY/eNe7tDcf1JQ/s640/Android_update_repo_flow.png" width="456" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Feel free to comment if you find these charts useful or if you think I should add or change things.&lt;br /&gt;&lt;br /&gt;/Mattias B&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-8304760030558699738?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/8304760030558699738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/05/android-open-source-project-workflow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8304760030558699738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8304760030558699738'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/05/android-open-source-project-workflow.html' title='Android Open Source Project workflow'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_fcXaF6gx74U/S-bUr2q2qPI/AAAAAAAAADQ/lUZ77NPCN7E/s72-c/Android_update_workflow.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-8115967869278771721</id><published>2010-04-21T14:14:00.000+02:00</published><updated>2010-04-21T14:14:40.033+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Using Checkstyle with Android Open Source Project</title><content type='html'>&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt;&lt;span&gt;&lt;span style="font-size: small;"&gt;This post provides a small Checkstyle template that we have been using to conform with the &lt;a href="http://source.android.com/submit-patches/code-style-guide"&gt;code style guide&lt;/a&gt; proposed by the &lt;a href="http://source.android.com/"&gt;Android Open Source Project&lt;/a&gt;. For pure formatting issues also see&lt;a href="http://stackoverflow.com/questions/2480596/did-anyone-create-the-java-code-formatter-profile-for-eclipse-ide-that-conforms-t"&gt; &lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://stackoverflow.com/questions/2480596/did-anyone-create-the-java-code-formatter-profile-for-eclipse-ide-that-conforms-t"&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt;&lt;span&gt;&lt;span style="font-size: small;"&gt;this question  on stackoverflow&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Arial; font-size: x-small;"&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;1. Make  sure that the Checkstyle plugin is installed in Eclipse. If not, follow the steps below. Note that these instructions  are for Eclipse Galileo. If you are using another version, some of the  installation steps might differ.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  1. Open "Help" -&amp;gt; "Install New Software"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  2. Paste the link: http://eclipse-cs.sf.net/update into the "Work with:" field and click "Add..."&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  3. Name the site e.g. "Checkstyle"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  4. Check the box next to the latest version of the Checkstyle plugin and press "Next-&amp;gt;"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  5. Follow the instructions to complete the installation&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;2. Save  the contents below to a new xml file and place it on a location of your choice.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;3. Open  "Window" -&amp;gt; "Preferences" and choose Checkstyle&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;4. Press  "New..."&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;5. Fill  in the configuration properties&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  "Type: External Configuration File"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  "Name: Android checkstyle by Enea"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  "Location:" Browse to the saved android_cs.xml file&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;6. Press  OK twice&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;7. Right  click on your Android project and choose Properties&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;8.  Choose Checkstyle and check the box "Checkstyle active for this project"&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;9.  Select "Android checkstyle by Enea" from the drop down list&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;10.  Rebuild the project to analyze your code&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;Done!&lt;br&gt;&lt;br /&gt;Karin, Fredrik and Karl&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;Note: If  you want to edit the checkstyle configuration open "Window" -&amp;gt; "Preferences" and choose Checkstyle. &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;span&gt;Mark the  Check Configuration you want to edit and press "Properties..."&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Save this to an .xml file.&lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE module PUBLIC &amp;quot;-//Puppy Crawl//DTD Check Configuration 1.3//EN&amp;quot; &amp;quot;https://home.enea.com/dtds/,DanaInfo=www.puppycrawl.com,CT=dtd+configuration_1_3.dtd&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;    This configuration file was written by the eclipse-cs plugin configuration editor&lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt;    Checkstyle-Configuration: Android checkstyle by Enea&lt;br /&gt;    Description: none&lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;module name=&amp;quot;Checker&amp;quot;&amp;gt;&lt;br /&gt;  &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;warning&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;TreeWalker&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;tabWidth&amp;quot; value=&amp;quot;4&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;JavadocMethod&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;logLoadErrors&amp;quot; value=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;suppressLoadErrors&amp;quot; value=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;JavadocType&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;JavadocVariable&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;JavadocStyle&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ConstantName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;LocalFinalVariableName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;LocalVariableName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MemberName&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.comment&amp;quot; value=&amp;quot;only public starts without m&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;applyToProtected&amp;quot; value=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;applyToPrivate&amp;quot; value=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MethodName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;PackageName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ParameterName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;StaticVariableName&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.comment&amp;quot; value=&amp;quot;starts with 's'&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;format&amp;quot; value=&amp;quot;^[s][a-zA-Z0-9]*$&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;TypeName&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;AvoidStarImport&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;IllegalImport&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;RedundantImport&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;UnusedImports&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;LineLength&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MethodLength&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ParameterNumber&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;EmptyForIteratorPad&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MethodParamPad&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;NoWhitespaceAfter&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;tokens&amp;quot; value=&amp;quot;BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;NoWhitespaceBefore&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;OperatorWrap&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ParenPad&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;TypecastParenPad&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;WhitespaceAfter&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;WhitespaceAround&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ModifierOrder&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;RedundantModifier&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;AvoidNestedBlocks&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;EmptyBlock&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;LeftCurly&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;NeedBraces&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;RightCurly&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;AvoidInlineConditionals&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;DoubleCheckedLocking&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;EmptyStatement&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;EqualsHashCode&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;HiddenField&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;IllegalInstantiation&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;InnerAssignment&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MagicNumber&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MissingSwitchDefault&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;RedundantThrows&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;logLoadErrors&amp;quot; value=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;suppressLoadErrors&amp;quot; value=&amp;quot;true&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;SimplifyBooleanExpression&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;SimplifyBooleanReturn&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;DesignForExtension&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;FinalClass&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;HideUtilityClassConstructor&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;InterfaceIsType&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;VisibilityModifier&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;ArrayTypeStyle&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;FinalParameters&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;TodoComment&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;UpperEll&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MethodLength&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;max&amp;quot; value=&amp;quot;40&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;MemberName&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.comment&amp;quot; value=&amp;quot;non public members should start with m&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;applyToPublic&amp;quot; value=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;format&amp;quot; value=&amp;quot;^[m][a-zA-Z0-9]*$&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;    &amp;lt;module name=&amp;quot;LineLength&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&amp;quot;max&amp;quot; value=&amp;quot;100&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;JavadocPackage&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;NewlineAtEndOfFile&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;Translation&amp;quot;&amp;gt;&amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;FileTabCharacter&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module name=&amp;quot;RegexpSingleline&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;severity&amp;quot; value=&amp;quot;ignore&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;format&amp;quot; value=&amp;quot;\s+$&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;property name=&amp;quot;message&amp;quot; value=&amp;quot;Line has trailing spaces.&amp;quot;&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;metadata name=&amp;quot;net.sf.eclipsecs.core.lastEnabledSeverity&amp;quot; value=&amp;quot;inherit&amp;quot;&amp;gt;&amp;lt;/metadata&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;&amp;lt;/module&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-8115967869278771721?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/8115967869278771721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/04/using-checkstyle-with-android-open.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8115967869278771721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8115967869278771721'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/04/using-checkstyle-with-android-open.html' title='Using Checkstyle with Android Open Source Project'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-6718983655039983102</id><published>2010-03-22T10:34:00.002+01:00</published><updated>2010-12-08T10:36:04.702+01:00</updated><title type='text'>Share memory using ashmem and binder in the android framework</title><content type='html'>To share memory between different processes in the android framework ashmem can be used. Ashmem is a android shared memory addon to the linux kernel. &lt;br /&gt;Ashmem has reference counting so that if many processes use the same area the area will not be removed until all processes has released it, the memory is also virtual and not physically contiguous. If physically contiguous memory is needed like for hardware reasons pmem can be used, but it has no reference counting and is not part of standard Android kernel. &lt;br /&gt;In this blog post we will concentrate only on ashmem.&lt;br /&gt;&lt;br /&gt;Ashmem is allocated via ashmem_create_region() that gives you an file descriptor then you use mmap() on it to get a memory area:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;int fd = ashmem_create_region("SharedRegionName", size); if(fd == 0) {&lt;br /&gt;  data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);&lt;br /&gt;  if(data != MAP_FAILED)&lt;br /&gt;  {&lt;br /&gt;    /* It works do your stuff*/&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But this will not solve your problem on how to share the memory area. The first problem is that the memory pointer "data" in our example above is per process and can't be shared. The next problem is that for security reasons the name "SharedRegionName" in the example above are not shared between processes. The "other" process that want to access the same shared memory area can't use a ashmem_create_region() with the same name to get access to the same physical memory area. Instead the file descriptor (fd in the example above) needs to be used in a new mmap() in the "other" process. Here comes the third problem, the file descriptor are per process and can't be shared with the other process just like that. Bummer!&lt;br /&gt;&lt;br /&gt;The solution is to share the file descriptor with the binder since the binder has special functions that can be used to transfer file descriptors over it's interface. &lt;br /&gt;To help you with ashmem handeling and file descriptor sharing the class MemoryHeapBase can be used. &lt;br /&gt;&lt;br /&gt;To transfer the MemoryHeapBase object you can use the asBinder() on the IMemoryHeap interface class on the server side to transfer the needed information to setup an new area on the client side mapped to the same physical memory.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sp&amp;lt;imemoryheap&amp;gt; memHeap = ...&lt;br /&gt;reply-&amp;gt;writeStrongBinder(memHeap-&amp;gt;asBinder())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On the client side the MemoryHeapBase class will take care of all the needed stuff for you and all you need to do in your binder wrapper class is something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sp&amp;lt;imemoryheap&amp;gt; memHeap;&lt;br /&gt;memHeap = interface_cast&amp;lt;imemoryheap&amp;gt; (reply.readStrongBinder());&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Please remember that the mmap:ed memories virtual address is not equal to the physical address even more important that the virtual address is different to each process and might be different for every call to the&lt;br /&gt;getBufferMemPointer() function even if the same ashmem region is used so be careful if you have stored your pointer somewhere and still operate on it.&lt;br /&gt;&lt;br /&gt;Here is a complete example setting up everything needed to get this working.&lt;br /&gt;&lt;br /&gt;Interface header: IEneaBuffer.h&lt;br /&gt;&lt;pre&gt;/*&lt;br /&gt; * IEneabuffer.h&lt;br /&gt; *  Created on: 19 mars 2010  Author: Zingo Andersen&lt;br /&gt; *  License: Public Domain (steal and use what you like)&lt;br /&gt; *&lt;br /&gt; * Buffer classes to handle the binder communication  */&lt;br /&gt;&lt;br /&gt;#ifndef IENEABUFFER_H_&lt;br /&gt;#define IENEABUFFER_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;utils/RefBase.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/IInterface.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/Parcel.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/IMemory.h&amp;gt;&lt;br /&gt;#include &amp;lt;utils/Timers.h&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace android {&lt;br /&gt;&lt;br /&gt;class IEneaBuffer: public IInterface&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;  DECLARE_META_INTERFACE(EneaBuffer);&lt;br /&gt;  virtual sp&amp;lt;IMemoryHeap&amp;gt;           getBuffer() = 0;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;/* --- Server side --- */&lt;br /&gt;&lt;br /&gt;class BnEneaBuffer: public BnInterface&amp;lt;IEneaBuffer&amp;gt;&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;  virtual status_t    onTransact( uint32_t code,&lt;br /&gt;                                  const Parcel&amp; data,&lt;br /&gt;                                  Parcel* reply,&lt;br /&gt;                                  uint32_t flags = 0);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;}; // namespace android&lt;br /&gt;&lt;br /&gt;#endif /* IENEABUFFER_H_ */&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Interface class: IEneaBuffer.cpp&lt;br /&gt;&lt;pre&gt;/*&lt;br /&gt; * IEneaBuffer.cpp&lt;br /&gt; *  Created on: 19 mars 2010  Author: Zingo Andersen&lt;br /&gt; *  License: Public Domain (steal and use what you like)&lt;br /&gt; *&lt;br /&gt; * Buffer classes to handle the binder communication&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;//#define LOG_TAG "IEneaBuffer"&lt;br /&gt;#include &amp;lt;utils/Log.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/MemoryHeapBase.h&amp;gt;&lt;br /&gt;#include &amp;lt;IEneaBuffer.h&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace android {&lt;br /&gt;&lt;br /&gt;enum {&lt;br /&gt;    GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;/* --- Client side --- */&lt;br /&gt;class BpEneaBuffer: public BpInterface&amp;lt;IEneaBuffer&amp;gt;&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;  BpEneaBuffer(const sp&amp;lt;IBinder&amp;gt;&amp; impl) : BpInterface&amp;lt;IEneaBuffer&amp;gt;(impl)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  sp&amp;lt;IMemoryHeap&amp;gt; getBuffer()&lt;br /&gt;  {&lt;br /&gt;    Parcel data, reply;&lt;br /&gt;    sp&amp;lt;IMemoryHeap&amp;gt; memHeap = NULL;&lt;br /&gt;    data.writeInterfaceToken(IEneaBuffer::getInterfaceDescriptor());&lt;br /&gt;    // This will result in a call to the onTransact()&lt;br /&gt;    // method on the server in it's context (from it's binder threads)&lt;br /&gt;    remote()-&amp;gt;transact(GET_BUFFER, data, &amp;reply);&lt;br /&gt;    memHeap = interface_cast&amp;lt;IMemoryHeap&amp;gt; (reply.readStrongBinder());&lt;br /&gt;    return memHeap;&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;IMPLEMENT_META_INTERFACE(EneaBuffer, "android.vendor.IEneaBuffer");&lt;br /&gt;&lt;br /&gt;/* --- Server side --- */&lt;br /&gt;&lt;br /&gt;status_t BnEneaBuffer::onTransact(uint32_t code, const Parcel&amp; data, Parcel* reply, uint32_t flags)&lt;br /&gt;{&lt;br /&gt;  switch (code)&lt;br /&gt;  {&lt;br /&gt;    case GET_BUFFER:&lt;br /&gt;    {&lt;br /&gt;      CHECK_INTERFACE(IEneaBuffer, data, reply);&lt;br /&gt;      sp&amp;lt;IMemoryHeap&amp;gt; Data = getBuffer();&lt;br /&gt;      if (Data != NULL)&lt;br /&gt;      {&lt;br /&gt;        reply-&amp;gt;writeStrongBinder(Data-&amp;gt;asBinder());&lt;br /&gt;      }&lt;br /&gt;      return NO_ERROR;&lt;br /&gt;      break;&lt;br /&gt;    }&lt;br /&gt;    default:&lt;br /&gt;      return BBinder::onTransact(code, data, reply, flags);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}; // namespace android&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then use it in your server class by inherit the server class with something like this:&lt;br /&gt;&lt;br /&gt;Server command: EneaBufferServer.cpp&lt;br /&gt;&lt;pre&gt;/*&lt;br /&gt; * EneaBufferServer.cpp&lt;br /&gt; *  Created on: 19 mars 2010  Author: Zingo Andersen&lt;br /&gt; *  License: Public Domain (steal and use what you like)&lt;br /&gt; *&lt;br /&gt; *  The Server will create a shared area that the client will then use&lt;br /&gt; *  The server will initiate the first int in the area and print it's value every&lt;br /&gt; *  5s. If you start the client in parallell it will try to change this value&lt;br /&gt; *  (value=value+1).&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#include "IEneaBuffer.h"&lt;br /&gt;#include &amp;lt;binder/MemoryHeapBase.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/IServiceManager.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/IPCThreadState.h&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace android {&lt;br /&gt;&lt;br /&gt;#define MEMORY_SIZE 10*1024  /* 10Kb shared memory*/&lt;br /&gt;&lt;br /&gt;class EneaBufferService : public BnEneaBuffer {&lt;br /&gt;public:&lt;br /&gt;  static void instantiate();&lt;br /&gt;  EneaBufferService();&lt;br /&gt;  virtual ~EneaBufferService();&lt;br /&gt;  virtual sp&amp;lt;IMemoryHeap&amp;gt; getBuffer();&lt;br /&gt;private:&lt;br /&gt;  sp&amp;lt;MemoryHeapBase&amp;gt; mMemHeap;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;sp&amp;lt;IMemoryHeap&amp;gt; EneaBufferService::getBuffer()&lt;br /&gt;{&lt;br /&gt;  return mMemHeap;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void EneaBufferService::instantiate()&lt;br /&gt;{&lt;br /&gt;  status_t status;&lt;br /&gt;  status = defaultServiceManager()-&amp;gt;addService(String16("vendor.enea.Buffer"), new EneaBufferService());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;EneaBufferService::EneaBufferService()&lt;br /&gt;{&lt;br /&gt;  //The memory is allocated using a MemoryHeapBase, and thereby is using ashmem&lt;br /&gt;  mMemHeap = new MemoryHeapBase(MEMORY_SIZE);&lt;br /&gt;  unsigned int *base = (unsigned int *) mMemHeap-&amp;gt;getBase();&lt;br /&gt;  *base=0xdeadcafe; //Initiate first value in buffer&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;EneaBufferService::~EneaBufferService()&lt;br /&gt;{&lt;br /&gt;  mMemHeap = 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static sp&amp;lt;IMemoryHeap&amp;gt; receiverMemBase;&lt;br /&gt;&lt;br /&gt;unsigned int * getBufferMemPointer(void)&lt;br /&gt;{&lt;br /&gt;  static sp&amp;lt;IEneaBuffer&amp;gt; eneaBuffer;&lt;br /&gt;&lt;br /&gt;  /* Get the buffer service */&lt;br /&gt;  if (eneaBuffer == NULL)&lt;br /&gt;  {&lt;br /&gt;    sp&amp;lt;IServiceManager&amp;gt; sm = defaultServiceManager();&lt;br /&gt;    sp&amp;lt;IBinder&amp;gt; binder;&lt;br /&gt;    binder = sm-&amp;gt;getService(String16("vendor.enea.Buffer"));&lt;br /&gt;    if (binder != 0)&lt;br /&gt;    {&lt;br /&gt;      eneaBuffer = IEneaBuffer::asInterface(binder);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  if (eneaBuffer == NULL)&lt;br /&gt;  {&lt;br /&gt;    LOGE("The buffer service is not published");&lt;br /&gt;    return (unsigned int *)-1; /* return an errorcode... */&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    receiverMemBase = eneaBuffer-&amp;gt;getBuffer();&lt;br /&gt;    return (unsigned int *) receiverMemBase-&amp;gt;getBase();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;using namespace android;&lt;br /&gt;&lt;br /&gt;int main(int argc, char** argv)&lt;br /&gt;{&lt;br /&gt; unsigned int *base;&lt;br /&gt;&lt;br /&gt;    EneaBufferService::instantiate();&lt;br /&gt;&lt;br /&gt;    //Create binder threads for this "server"&lt;br /&gt;    ProcessState::self()-&amp;gt;startThreadPool();&lt;br /&gt;    LOGD("Server is up and running");&lt;br /&gt;&lt;br /&gt;    base = getBufferMemPointer();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    for(;;)&lt;br /&gt;    {&lt;br /&gt;     LOGD("EneaBufferServer base=%p Data=0x%x", base,*base);&lt;br /&gt;     sleep(5);&lt;br /&gt;    }&lt;br /&gt;    // wait for threads to stop&lt;br /&gt;    //   IPCThreadState::self()-&amp;gt;joinThreadPool();&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You need add the following line to register the service in the file frameworks/base/cmds/servicemanager/service_manager.c&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;{ AID_MEDIA, "vendor.enea.Buffer" },&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On the client process side you can use something like the code snippet below to get the memory pointer.&lt;br /&gt;NOTE: MemoryHeapBase is based on strong pointer and will be "magical" ref counted and removed thats why the client put the object pointer in a static variable in the example below to keep it from being removed.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;/*&lt;br /&gt; * EneaBufferClient.cpp&lt;br /&gt; *  Created on: 19 mars 2010  Author: Zingo Andersen&lt;br /&gt; *  License: Public Domain (steal and use what you like)&lt;br /&gt; *&lt;br /&gt; *  Get the shared memory buffer from the server and change the first int value&lt;br /&gt; *  by adding one to it. The Server should be running in parallell pleas view&lt;br /&gt; *  the logcat for the result&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;#include "IEneaBuffer.h"&lt;br /&gt;#include &amp;lt;binder/MemoryHeapBase.h&amp;gt;&lt;br /&gt;#include &amp;lt;binder/IServiceManager.h&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace android {&lt;br /&gt;static sp&amp;lt;IMemoryHeap&amp;gt; receiverMemBase;&lt;br /&gt;&lt;br /&gt;unsigned int * getBufferMemPointer(void)&lt;br /&gt;{&lt;br /&gt;  static sp&amp;lt;IEneaBuffer&amp;gt; eneaBuffer = 0;&lt;br /&gt;&lt;br /&gt;  /* Get the buffer service */&lt;br /&gt;  if (eneaBuffer == NULL)&lt;br /&gt;  {&lt;br /&gt;    sp&amp;lt;IServiceManager&amp;gt; sm = defaultServiceManager();&lt;br /&gt;    sp&amp;lt;IBinder&amp;gt; binder;&lt;br /&gt;    binder = sm-&amp;gt;getService(String16("vendor.enea.Buffer"));&lt;br /&gt;    if (binder != 0)&lt;br /&gt;    {&lt;br /&gt;      eneaBuffer = IEneaBuffer::asInterface(binder);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  if (eneaBuffer == NULL)&lt;br /&gt;  {&lt;br /&gt;    LOGE("The EneaBufferServer is not published");&lt;br /&gt;    return (unsigned int *)-1; /* return an errorcode... */&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    receiverMemBase = eneaBuffer-&amp;gt;getBuffer();&lt;br /&gt;    return (unsigned int *) receiverMemBase-&amp;gt;getBase();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;using namespace android;&lt;br /&gt;&lt;br /&gt;int main(int argc, char** argv)&lt;br /&gt;{&lt;br /&gt; // base could be on same address as Servers base but this&lt;br /&gt; // is purely by luck do NEVER rely on this. Linux memory&lt;br /&gt; // management may put it wherever it likes.&lt;br /&gt;    unsigned int *base = getBufferMemPointer();&lt;br /&gt;    if(base != (unsigned int *)-1)&lt;br /&gt;    {&lt;br /&gt;     LOGD("EneaBufferClient base=%p Data=0x%x\n",base, *base);&lt;br /&gt;       *base = (*base)+1;&lt;br /&gt;       LOGD("EneaBufferClient base=%p Data=0x%x CHANGED\n",base, *base);&lt;br /&gt;        receiverMemBase = 0;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;     LOGE("Error shared memory not available\n");&lt;br /&gt;    }&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And my Android.mk file for this:&lt;br /&gt;&lt;pre&gt;# Ashmem shared buffer example&lt;br /&gt;# Created on: 19 mars 2010  Author: Zingo Andersen # License: Public Domain (steal and use what you like)&lt;br /&gt;&lt;br /&gt;LOCAL_PATH:= $(call my-dir)&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# BufferServer&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES:=        \&lt;br /&gt; IEneaBuffer.cpp      \&lt;br /&gt; EneaBufferServer.cpp \&lt;br /&gt;   &lt;br /&gt;LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE:= EneaBufferServer&lt;br /&gt;&lt;br /&gt;LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferServer\"&lt;br /&gt;&lt;br /&gt;LOCAL_PRELINK_MODULE:=false&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# BufferClient&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES:=        \&lt;br /&gt; IEneaBuffer.cpp      \&lt;br /&gt; EneaBufferClient.cpp \&lt;br /&gt;   &lt;br /&gt;LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE:= EneaBufferClient&lt;br /&gt;&lt;br /&gt;LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferClient\"&lt;br /&gt;&lt;br /&gt;LOCAL_PRELINK_MODULE:=false&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;/Rebecka &amp;amp; Zingo&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-6718983655039983102?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/6718983655039983102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-binder-in.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6718983655039983102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6718983655039983102'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-binder-in.html' title='Share memory using ashmem and binder in the android framework'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-1653010586807848803</id><published>2010-02-04T20:00:00.000+01:00</published><updated>2010-02-04T20:00:23.916+01:00</updated><title type='text'>Everyone wants to learn more about Android</title><content type='html'>It's been a really busy start on the new year here at the Enea Android Team. We've been fully occupied providing Android trainings all over the place. The whole Q1 is fully scheduled (if you're interested you could take a look in our training brochure at &lt;a href="http://www.enea.com/android"&gt;www.enea.com/android&lt;/a&gt;). On top of that we have MWC 2010 in Barcelona coming up, where we are working on a really cool demo. We apologize for not sharing with you this last month, but please stay tuned. Interesting posts will come shortly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enea Android Team&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-1653010586807848803?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/1653010586807848803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/02/everyone-wants-to-learn-more-about.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1653010586807848803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1653010586807848803'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/02/everyone-wants-to-learn-more-about.html' title='Everyone wants to learn more about Android'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-9097256956623480341</id><published>2010-02-03T11:23:00.000+01:00</published><updated>2010-02-03T11:23:04.364+01:00</updated><title type='text'>Using Android to control Lego Mindstorms</title><content type='html'>This is a short post on the more entertaining side of Android showing a project that the Enea team in Linköping, Sweden, prepared for an expo. It is a one minute video from the demonstration.&lt;br /&gt;&lt;br /&gt;It is two LEGO Mindstorms robots controlled by one HTC Hero Android phone. The Hero is running an Android application written by Enea Linköping that send motor commands to the LEGO brick. LEGO has been kind enough to put a Bluetooth chip in the Mindstorms NXT controller. By using the built in demonstrational Bluetooth commands the NXT brick provides there is no need for an application to be downloaded into the NXT brick.&lt;br /&gt;There was however one obstacle in the limited Bluetooth support in Android OS version 1.5 (not supporting the Bluetooth serial port profile, SPP). Instead we used the wifi capabilities on the phone to send information to an Ubuntu Linux Laptop with a TCP/IP to Bluetooth tunnel (just a raw tunnel, no logic or programming). HTC has been rumored to be releasing Android OS version 2.1 (with Bluetooth) later in february and we hope to be able to put forth a new version that skip the WiFi laptop step.&lt;br /&gt;&lt;br /&gt;Video below:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/434hbckPz6o&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/434hbckPz6o&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-9097256956623480341?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/9097256956623480341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2010/02/using-android-to-control-lego.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/9097256956623480341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/9097256956623480341'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2010/02/using-android-to-control-lego.html' title='Using Android to control Lego Mindstorms'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-7200220187376876830</id><published>2009-12-29T09:31:00.001+01:00</published><updated>2009-12-29T09:49:42.196+01:00</updated><title type='text'>Adding a system server to the Android framework</title><content type='html'>Following our other posts about booting and the system server, here are some more details of how to add a service to the system server.&lt;br /&gt;&lt;br /&gt;It should be noted that extending the system server and other framework features is not recommended, as the code requires to be ported to future releases of the framework.&lt;br /&gt;The most common reason for adding a system server would be for supporting proprietary hardware.  &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Design considerations&lt;/b&gt;&lt;br /&gt;There are a few questions to be answered before implementing a system server, such as threads needed, application interfaces, and hardware interfaces. It's no easy task specifying your server design, but considering the following will hopefully help you out:&lt;br /&gt;1. How frequently will the server run? If the server is only needed occasionaly, it might very well run within the system server context, even though the most common way is give it its own thread. A typical infrequent server is the Headset observer, which will only run when a headset is connected or removed.&lt;br /&gt;2. How is the hardware accessed? Standard hardware could be accessible through device file access and file observers, but the best solution is no doubt to implement a HAL library. The HAL makes it easier to port your server to other hardware, and also makes it possible to run some functionality in native threads if needed.&lt;br /&gt;3. Application interfacing? It is sometimes possible to get away with using intents and implementing your server as a receiver, but for anything but the simplest requests, you will no doubt have to use aidl.&lt;br /&gt;4. Extending the framework? If you want to make your new interface visible to the applications, you will have to update the api description and build your own sdk. (That is easily done with "make update-api", followed by "make sdk".) However, if you only want the your nifty features to be accessible from your own proprietary applications, you should make use of the javadoc @hide-option for your interface. &lt;br /&gt;5. Is there another way? Adding your own server adds migration work for new releases of the framework. To minimise files added, it's easy to be tempted to alter existing services instead of adding your own. That is fine to do, but keep in mind that if some functionality changes, third-party applications may not work anymore. Again, if your server will only be accessed from a proprietary application and not publicly available, consider adding the code to the application instead.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Code sample&lt;/b&gt;&lt;br /&gt;Following is an example of a proprietary service, that knows how to set a value. For simplicity, the code is just added to the framework. For a production implementation, the code should go into the vendor directory.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Specifying the interface.&lt;/b&gt;&lt;br /&gt;This example uses aidl, so the first step is to add an interface definition file:&lt;br /&gt;&lt;i&gt;frameworks/base/core/java/android/os/IEneaService.aidl&lt;/i&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;package android.os;&lt;br /&gt;&lt;br /&gt;interface IEneaService {&lt;br /&gt;&amp;nbsp; /**  &lt;br /&gt;&amp;nbsp; * {@hide}&lt;br /&gt;&amp;nbsp; */&lt;br /&gt;&amp;nbsp; void setValue(int val);&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The interface file will need to be added to the build system:&lt;br /&gt;&lt;i&gt;frameworks/base/Android.mk&lt;/i&gt;&lt;br /&gt;Add the following around line 165 (the end of the list of SRC_FILES):&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;core/java/android/os/IEneaService.aidl \&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Implementing the server&lt;/b&gt;&lt;br /&gt;The service spawns a worker thread that will do all the work, as part of the system server process. Since the service is created by the system server, it will need to be located somewhere where the system server can find it.&lt;br /&gt;&lt;i&gt;frameworks/base/services/java/com/android/server/EneaService.java&lt;/i&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;package com.android.server;&lt;br /&gt;&lt;br /&gt;import android.content.Context;&lt;br /&gt;import android.os.Handler;&lt;br /&gt;import android.os.IEneaService;&lt;br /&gt;import android.os.Looper;&lt;br /&gt;import android.os.Message;&lt;br /&gt;import android.os.Process;&lt;br /&gt;import android.util.Log;&lt;br /&gt;&lt;br /&gt;public class EneaService extends IEneaService.Stub {&lt;br /&gt;&amp;nbsp; private static final String TAG = "EneaService";&lt;br /&gt;&amp;nbsp; private EneaWorkerThread mWorker;&lt;br /&gt;&amp;nbsp; private EneaWorkerHandler mHandler;&lt;br /&gt;&amp;nbsp; private Context mContext;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; public EneaService(Context context) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; super();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mContext = context;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mWorker = new EneaWorkerThread("EneaServiceWorker");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mWorker.start();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Log.i(TAG, "Spawned worker thread");&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; public void setValue(int val)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Log.i(TAG, "setValue " + val);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Message msg = Message.obtain();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; msg.what = EneaWorkerHandler.MESSAGE_SET;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; msg.arg1 = val;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; mHandler.sendMessage(msg);&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; private class EneaWorkerThread extends Thread{    &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public EneaWorkerThread(String name) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; super(name);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void run() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Looper.prepare();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mHandler = new EneaWorkerHandler();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Looper.loop();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }    &lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; private class EneaWorkerHandler extends Handler {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static final int MESSAGE_SET = 0;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void handleMessage(Message msg) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (msg.what == MESSAGE_SET) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Log.i(TAG, "set message received: " + msg.arg1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (Exception e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Log, don't crash!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Log.e(TAG, "Exception in EneaWorkerHandler.handleMessage:", e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;You may want to add to the log printouts the thread id or name just to visualise which thread the code is executing in.&lt;br /&gt;&lt;br /&gt;All that's left to do now is to type &lt;i&gt;make&lt;/i&gt; to build the repository, and then start up the emulator. Using logcat, you will find the message saying that the thread has been spawned.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Test program&lt;/b&gt;&lt;br /&gt;You probably want to test your service as well. For this you can create a "Hello World" activity using the project wizard. Place the project in the &lt;i&gt;vendor/enea&lt;/i&gt; directory.&lt;br /&gt;&lt;br /&gt;In the main activity class of your test program, add the following lines to &lt;i&gt;onCreate()&lt;/i&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;IEneaService em = IEneaService.Stub.asInterface(ServiceManager.getService("EneaService"));&lt;br /&gt;try {&lt;br /&gt;&amp;nbsp; em.setValue(7); // Any value would do, really.&lt;br /&gt;} catch (Exception e) {&lt;br /&gt;&amp;nbsp; e.printStackTrace();&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;You will also need to import android.os.IEneaService and of course add an apropriate Android.mk to build your test program.&lt;br /&gt;&lt;br /&gt;Start your test program and look in the log. You should now find the "set value"-messages.&lt;br /&gt;&lt;br /&gt;Cheers&lt;br /&gt;Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-7200220187376876830?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/7200220187376876830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/12/adding-system-server-to-android.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/7200220187376876830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/7200220187376876830'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/12/adding-system-server-to-android.html' title='Adding a system server to the Android framework'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-5591235242273038715</id><published>2009-12-21T17:20:00.004+01:00</published><updated>2010-12-08T10:50:30.105+01:00</updated><title type='text'>Howto setup a android project in Eclipse that access both Java and C/C++ code</title><content type='html'>If you follow the instructions on&amp;nbsp;&lt;a href="http://source.android.com/using-eclipse"&gt;http://source.android.com/using-eclipse&lt;/a&gt; you will only have a Java project and will only see the C/C++ project files as 2:nd class citizens without any indexing. I will propose a another solution that will combine the ideas from &lt;a href="http://lorinc.blogspot.com/2006/10/how-to-mix-java-and-c-code-in-singe.html"&gt;http://lorinc.blogspot.com/2006/10/how-to-mix-java-and-c-code-in-singe.html&lt;/a&gt;.&lt;br /&gt;1. Copy the already available Java setup &lt;br /&gt;&lt;pre&gt;$ cd &amp;lt;your mydroid folder&amp;gt;&lt;br /&gt;$ cp development/ide/eclipse/.classpath .&lt;br /&gt;# You might need to make the copy writable (describe on android.com) &lt;br /&gt;$ chmod u+w .classpath &lt;/pre&gt;2. From Eclipse create a new C++ project File -&amp;gt; New -&amp;gt; Other, select C/C++ -&amp;gt; C++ Project give it a project name and uncheck "Use default location"&lt;br /&gt;and give it the path to your  directory (often called the mydroid dir)&lt;br /&gt;Select Project Type: "Makefile project" -&amp;gt; "Empty Project", let the "-- Other Toolchain" be selected and press "Finish"&lt;br /&gt;&lt;br /&gt;3. Add in Java to the same project&lt;br /&gt;Close Eclipse as you will edit a file it holds open and will overwrite otherwise Now a /.project file has been created open it in a text editor and add the following:&lt;br /&gt;&lt;pre&gt;&amp;lt;buildCommand&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;org.eclipse.jdt.core.javabuilder&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;arguments&amp;gt;&amp;lt;/arguments&amp;gt;&lt;br /&gt;&amp;lt;/buildCommand&amp;gt;&lt;br /&gt;&lt;/pre&gt;and&lt;br /&gt;&lt;pre&gt;&amp;lt;nature&amp;gt;org.eclipse.jdt.core.javanature&amp;lt;/nature&amp;gt;&lt;br /&gt;&lt;/pre&gt;as described here:&lt;br /&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;projectdescription&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;android zoom2&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;comment&amp;gt;&amp;lt;/comment&amp;gt;&lt;br /&gt;    &amp;lt;projects&amp;gt;&lt;br /&gt;    &amp;lt;/projects&amp;gt;&lt;br /&gt;    &amp;lt;buildspec&amp;gt;&lt;br /&gt;------------------------------- below is added &lt;br /&gt;        &amp;lt;buildCommand&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;org.eclipse.jdt.core.javabuilder&amp;lt;/name&amp;gt;&lt;br /&gt;     &amp;lt;arguments&amp;gt;&lt;br /&gt;     &amp;lt;/arguments&amp;gt;&lt;br /&gt;        &amp;lt;/buildCommand&amp;gt;&lt;br /&gt;------------------------------- end of the added stuff &lt;br /&gt;        &amp;lt;buildcommand&amp;gt;&lt;br /&gt;            &amp;lt;name&amp;gt;org.eclipse.cdt.managedbuilder.core.genmakebuilder&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;triggers&amp;gt;clean,full,incremental,&amp;lt;/triggers&amp;gt;&lt;br /&gt;...&lt;br /&gt;        &amp;lt;/buildCommand&amp;gt;&lt;br /&gt;    &amp;lt;/buildSpec&amp;gt;&lt;br /&gt;    &amp;lt;natures&amp;gt;&lt;br /&gt;        &amp;lt;nature&amp;gt;org.eclipse.cdt.core.cnature&amp;lt;/nature&amp;gt;&lt;br /&gt; &amp;lt;nature&amp;gt;org.eclipse.cdt.core.ccnature&amp;lt;/nature&amp;gt;&lt;br /&gt;  &amp;lt;nature&amp;gt;org.eclipse.cdt.managedbuilder.core.managedBuildNature&amp;lt;/nature&amp;gt;&lt;br /&gt; &amp;lt;nature&amp;gt;org.eclipse.cdt.managedbuilder.core.ScannerConfigNature&amp;lt;/nature&amp;gt;&lt;br /&gt;------------------------------- below is added &lt;br /&gt; &amp;lt;nature&amp;gt;org.eclipse.jdt.core.javanature&amp;lt;/nature&amp;gt;&lt;br /&gt;------------------------------- end of the added stuff &lt;br /&gt;    &amp;lt;/natures&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;Now start eclipse again, now the Java classes are available in "Project Explorer" view and C/C++ files in "C/C++ Projects" view.&lt;br /&gt;&lt;br /&gt;One problem remain when you build it will use "make all" and that will not work and need to be changed to "make" this can be done if you right-click on the project and select "Properties"&lt;br /&gt;In the "Properties" window select "C/C++ Build" and click on the "Behaviour" tab and remove "all" from all the places where available.&lt;br /&gt;&lt;br /&gt;I still used the java heap enlargement in eclipse.ini from the first link by changing the numbers in eclipse.ini to the numbers below:&lt;br /&gt;&lt;pre&gt;-Xms128m&lt;br /&gt;-Xmx512m&lt;br /&gt;-XX:MaxPermSize=256m&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The standard eclipse from Ubuntu 9.10 (installed from synaptic) uses this file &lt;i&gt;/usr/lib/eclipse/eclipse.ini &lt;/i&gt;you need to be root to edit it e.g.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ sudo gedit /usr/lib/eclipse/eclipse.ini&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;/Zingo&lt;br /&gt;&lt;br /&gt;2010-12-08 Edit: removed wrongly formated spaces around &amp;lt; and &amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-5591235242273038715?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/5591235242273038715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/12/howto-setup-android-project-in-eclipse.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5591235242273038715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5591235242273038715'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/12/howto-setup-android-project-in-eclipse.html' title='Howto setup a android project in Eclipse that access both Java and C/C++ code'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-6105535727115911656</id><published>2009-12-03T17:51:00.001+01:00</published><updated>2010-01-07T10:31:36.939+01:00</updated><title type='text'>Ubuntu 9.10, Java 5 and the Android Open Source Project</title><content type='html'>Currently there is an issue with building the Android Open Source project on Ubuntu 9.10 Karmic Koala, or more specific with the Java 5 support. Java 5 was obsoleted by Sun on October 30 2009 and is not part of the Ubuntu 9.10 distribution. However there is still a need to use Java 5 for building Android since Java6 is not yet supported. There are two methods to get Java5 working on Ubuntu 9.10.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Method 1 - download and install from Sun&lt;/span&gt;&lt;br /&gt;This method will let you install the Java5 JDK in a separate directory and add it to the path when&lt;br /&gt;&lt;br /&gt;Download the Java5 JDK for Linux from&lt;a href="http://java.sun.com/javase/downloads/5u21/jdk"&gt; http://java.sun.com/javase/downloads/5u21/jdk&lt;/a&gt;&lt;br /&gt;This is a binary file that you should save to a suitable location like ~/tools&lt;br /&gt;In order to make i executable chmod the file as&lt;br /&gt;&lt;pre&gt;$ chmod 777 jdk-1_5_0_21-linux-i586.bin&lt;br /&gt;&lt;/pre&gt;and run it&lt;br /&gt;&lt;pre&gt;$ ./jdk-1_5_0_21-linux-i586.bin&lt;br /&gt;&lt;/pre&gt;This will install the jdk to the current directory.&lt;br /&gt;To use the JDK5 tools you need to add it first in the path before building the Android Open Source Project&lt;br /&gt;&lt;pre&gt;$ export PATH=~/tools/jdk1.5.0_21/bin:$PATH&lt;br /&gt;&lt;/pre&gt;This allows you to remove the JDK5 from the path when not building Android and use the standard Java settings instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Method 2 - use the Ubuntu 9.04 repositories to get Java5&lt;/span&gt;&lt;br /&gt;This method adds the Jaunty repositories and installs Java5 as the default java setting in the system. Open the sources file (/etc/apt/sources.list) for editing, as root&lt;br /&gt;&lt;pre&gt;$ sudo gedit /etc/apt/sources.list&lt;br /&gt;&lt;/pre&gt;and add:&lt;br /&gt;&lt;pre&gt;deb http://us.archive.ubuntu.com/ubuntu/ jaunty multiverse&lt;br /&gt;deb http://us.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;save the file and close gedit. Next sync your sources by running&lt;br /&gt;&lt;pre&gt;$ sudo apt-get update&lt;br /&gt;&lt;/pre&gt;and install&lt;br /&gt;&lt;pre&gt;$ sudo apt-get install sun-java5-jdk&lt;br /&gt;&lt;/pre&gt;To set the system to use Java 5 you need to update your java alternatives by running&lt;br /&gt;&lt;pre&gt;$ sudo update-alternatives --config java&lt;br /&gt;&lt;/pre&gt;Choose java-1.5.0-sun and you should be done.&lt;br /&gt;&lt;br /&gt;Hopefully the Android Open Source Project will build with Java 6 shortly but the above solutions should get you going with platform work on Ubuntu 9.10.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-6105535727115911656?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/6105535727115911656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/12/ubuntu-910-java-5-and-android-open.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6105535727115911656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6105535727115911656'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/12/ubuntu-910-java-5-and-android-open.html' title='Ubuntu 9.10, Java 5 and the Android Open Source Project'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3912891367233510226</id><published>2009-11-20T13:25:00.005+01:00</published><updated>2010-02-11T15:44:47.720+01:00</updated><title type='text'>Train Tracker - our first Android application</title><content type='html'>Even though application development has not been the main focus of the Enea Android Competence Center we decided to give it a try in order to widen our knowledge. For a couple of weeks we have been working on an application called Train Tracker. The application is mainly aimed to be used as an internal reference. The application shows real time train traffic information from Swedish train stations, some of the main features are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Show all departing/arriving trains at a specific train station&lt;/li&gt;&lt;li&gt;Detect and warn for delayed trains.&lt;/li&gt;&lt;li&gt;Station search with auto complete text&lt;/li&gt;&lt;li&gt;Follow a train route (all arrival and departure times at all stations) for a specific train&lt;/li&gt;&lt;li&gt;Filter list of arrivals/departures (e.g. all departures from Lund towards Malmö)&lt;/li&gt;&lt;li&gt;Save a filter as a favourite. Favourites can be selected directly from the start page.&lt;/li&gt;&lt;li&gt;Set an alarm on train routes to get notified when the train is delayed.&lt;/li&gt;&lt;li&gt;Global search for stations and favourites integrated in Google Quick Search Box (Requires Android platform 1.6 or later and that Train Tracker is made searchable in Settings/Search/Searchable Items)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The information presented in the application is downloaded from &lt;a href="http://banverket.se/"&gt;http://banverket.se&lt;/a&gt;. Unfortunately Banverket was not willing to give us API access which is why our application is parsing HTML in order to get the information. This means that the application is likely to stop working if Banverket decides to change the layout of the webpage. Right now the application works quite well and if you want to try it out you can&amp;nbsp;&lt;a href="http://thisdroid.com/tt/TrainTracker.apk"&gt;download TrainTracker.apk here&lt;/a&gt;, or use your favorite barcode scanner to get it:&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_fcXaF6gx74U/S3QXQnEOjdI/AAAAAAAAADE/xZwKwK6Dg_4/s1600-h/TrainTracker1.0.1.apk.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_fcXaF6gx74U/S3QXQnEOjdI/AAAAAAAAADE/xZwKwK6Dg_4/s320/TrainTracker1.0.1.apk.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Keep in mind that the application language is Swedish and it can only show information from Swedish trains and train stations. Here are some screenshots from Train Tracker:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_fcXaF6gx74U/SwZqneJw8aI/AAAAAAAAAB8/etokDtQyEQ0/s1600/1_SelectStation.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_fcXaF6gx74U/SwZqneJw8aI/AAAAAAAAAB8/etokDtQyEQ0/s320/1_SelectStation.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;i&gt;Train Tracker start activity. Search for a station or select one of your saved favourites.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_fcXaF6gx74U/SwZqryD25LI/AAAAAAAAACE/Xa0_gA8LFC4/s1600/2_StationDepartures.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_fcXaF6gx74U/SwZqryD25LI/AAAAAAAAACE/Xa0_gA8LFC4/s320/2_StationDepartures.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Train Tracker station activity. In this view you will find all arrivals/departures of a specific station.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_fcXaF6gx74U/SwZqtn-FG_I/AAAAAAAAACM/jk27v10fa08/s1600/3_SetFilter.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_fcXaF6gx74U/SwZqtn-FG_I/AAAAAAAAACM/jk27v10fa08/s320/3_SetFilter.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Train Tracker filter activity. Here you can filter the list of arrivals/departures. Select “Spara Filter” to save the filter as a favourite. Select “Använd Filter” to apply the selected criteria.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqusUYoHI/AAAAAAAAACU/DztYxdHb6tw/s1600/4_ActivateAlarm.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqusUYoHI/AAAAAAAAACU/DztYxdHb6tw/s320/4_ActivateAlarm.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Back at the station activity.  This time filtered with the selected filter criteria and one of the departures has been expanded. Tapping the “Aktivera alarm” line will schedule an alarm for train 1067. Tapping The “Tåg 1067” line will take you to the train route activity for this train.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqv_HP1hI/AAAAAAAAACc/VDXKeV7EBMU/s1600/5_TrainRouteWithNotification.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqv_HP1hI/AAAAAAAAACc/VDXKeV7EBMU/s320/5_TrainRouteWithNotification.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Train Tracker train route activity.  At this view we display all train stops for a specific train. At the top of the screen a train delayed notification is received.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqxYCxC3I/AAAAAAAAACk/aGcsAOPOfw8/s1600/6_GoogleQuickSearchBar.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_fcXaF6gx74U/SwZqxYCxC3I/AAAAAAAAACk/aGcsAOPOfw8/s320/6_GoogleQuickSearchBar.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Global search in Google Quick Search Bar. Search hits from Train Tracker shows up together with ordinary search hits. Search hits gain higher priority in the search result list as they are selected.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;/Erik&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3912891367233510226?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3912891367233510226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/11/even-though-application-development-has.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3912891367233510226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3912891367233510226'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/11/even-though-application-development-has.html' title='Train Tracker - our first Android application'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_fcXaF6gx74U/S3QXQnEOjdI/AAAAAAAAADE/xZwKwK6Dg_4/s72-c/TrainTracker1.0.1.apk.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-2765865552965342251</id><published>2009-11-05T09:34:00.000+01:00</published><updated>2009-11-05T09:34:03.639+01:00</updated><title type='text'>Android report in Elektroniktidningen</title><content type='html'>Recently I wrote an expert report on Android for Swedish magazine Elektroniktidningen. This has now been published as a downloadable pdf, as part of their Embedded Expert initiative. &lt;br /&gt;The reports are in Swedish.&lt;br /&gt;&lt;a href="http://etn.se/50066"&gt;Look here&lt;/a&gt; for details. Other very interesting reports can be found &lt;a href="http://etn.se/expert"&gt;over here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Regards&lt;br /&gt;Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-2765865552965342251?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/2765865552965342251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/11/android-report-in-elektroniktidningen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/2765865552965342251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/2765865552965342251'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/11/android-report-in-elektroniktidningen.html' title='Android report in Elektroniktidningen'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-1892752392419924202</id><published>2009-10-16T13:47:00.000+02:00</published><updated>2009-10-16T13:47:21.617+02:00</updated><title type='text'>Examples on extending the framework</title><content type='html'>This post covers a couple of examples that are available in the Android open source project that provide a good start to exploring the framework and the JNI implementations in Android. If you are working with Android Open Source Project on hardware and want to test adding new API:s to the platform without breaking the structure these examples are really good.&lt;br /&gt;&lt;br /&gt;The reason you may want to do this is that you are creating a device with some new features that you want to be available for some specific applications shipped with the device. It is also a good exercise to run through in order to understand the frameworks used by Android. This is the preferred way to do this and to quote Dianne Hackborn on the official mailing lists (found &lt;a href="http://groups.google.com/group/android-porting/browse_thread/thread/4559c6864fc5fb80?hl=en"&gt;here&lt;/a&gt;): &lt;br /&gt;&lt;blockquote&gt;If you are going to allow the user to keep Market on their phone, and are adding any new features, please do this the official way: include your own shared library with the features that applications use, rather than having magic hacks in the framework for them. &lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The example for this reside in the &lt;i&gt;vendor/samples&lt;/i&gt; folder in the Android open source project. There are several components in this example:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The PlatformLibraryExample code itself which is a sample native library implementing some example platform functionality. &lt;/li&gt;&lt;li&gt;A java library that interfaces the platform library through JNI and exposes the API:s to applications. &lt;/li&gt;&lt;li&gt;A sample client application that uses this functionality &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;It is even possible to create an SDK add-on in order to have the added features easily available when developing applications. We will talk more about SDK add-ons in a later post.&lt;br /&gt;&lt;br /&gt;To understand what is in this sample start out by reading the readme file in &lt;i&gt;vendor/sample/frameworks/PlatformLibrary&lt;/i&gt;. This file describes the above components in more detail and will also tell you what you need to know in order to test the framework additions on a system.&lt;br /&gt;&lt;br /&gt;If you are like us and like to try things out on the platform and work directly with some features that are not currently available in Android it is a good thing to follow these examples. It removes the need for making changes directly in the framework when exploring the possibilities of the platform.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-1892752392419924202?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/1892752392419924202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/10/examples-on-extending-framework.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1892752392419924202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/1892752392419924202'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/10/examples-on-extending-framework.html' title='Examples on extending the framework'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-7929460437001034806</id><published>2009-09-07T11:24:00.000+02:00</published><updated>2009-09-07T11:24:31.136+02:00</updated><title type='text'>Officially a competence center</title><content type='html'>There was an announcement today that the Android team here at Enea have now officially morphed into the Enea Android Competence Center. Based on this it seems fitting to add a more general post here. Currently we are engaged in some external projects which I can't say very much about except the info on the new and expanded Android section on &lt;a href="http://www.enea.com/android"&gt;Enea's web site&lt;/a&gt;. But there is also a lot of other activity in the team.&lt;br /&gt;&lt;br /&gt;We have some application work going on where we aim to have something useful to share in a month or so. We also use that project to explore some areas around testing for Android and it is our intention to have some testing and application articles up here on the blog soon.&lt;br /&gt;&lt;br /&gt;In the lower layers we have been working a lot with the platform framework, build system and start up as you may know if you have been following the blog. Currently we are moving into the areas of performance and security and plan some activities around that in the coming months. This will probably reflect on the blog as well.&lt;br /&gt;&lt;br /&gt;During the summer we have been preparing flexible Android training with a focus on the platform level and that will be a part of what we offer in the competence center. There are some great people from the team that will lead these trainings. This does not mean that we will stop sharing things here on the blog. It is a way to offer some personal hands-on training for those of you who want to know more.&lt;br /&gt;&lt;br /&gt;The blog will remain a place for mostly technical articles and discussion but now you know a little bit more about us and what we aim to discuss here in the coming months. The team is very happy with this change since it means that we are now an official part of Enea and will be able to keep working on fun projects for that very interesting mobile technology platform known as Android.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-7929460437001034806?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/7929460437001034806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/09/officially-competence-center.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/7929460437001034806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/7929460437001034806'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/09/officially-competence-center.html' title='Officially a competence center'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-6534309724685427559</id><published>2009-09-01T15:06:00.001+02:00</published><updated>2009-09-01T15:08:56.924+02:00</updated><title type='text'>Starting an Android service after boot</title><content type='html'>After some consideration we decided that we should have a post about adding a regular Android service at boot and not just consider the cases where you have to modify the platform itself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Simple boot service example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The key to this is the broadcast action &lt;i&gt;android.intent.action.BOOT_COMPLETED&lt;/i&gt; that is sent out once the platform boot is complete. To perform an action on boot you need to include a broadcast receiver in your application that registers for this intent. The rest of the implementation follows the standard design for Android services and applications.&lt;br /&gt;I have a small example that adds an Android service to perform a similar task as the native service that we had in the blog post about the init process. The service will start up at boot and then write something to the log at regular intervals. The first part we need is the broadcast receiver to take care of the boot intent:&lt;br /&gt;&lt;pre&gt;package com.enea.training.bootdemo;&lt;br /&gt;&lt;br /&gt;import android.content.BroadcastReceiver;&lt;br /&gt;import android.content.Context;&lt;br /&gt;import android.content.Intent;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Simple receiver that will handle the boot completed intent and send the intent to &lt;br /&gt; * launch the BootDemoService.&lt;br /&gt; * @author BMB&lt;br /&gt; *&lt;br /&gt; */&lt;br /&gt;public class BootDemoReceiver extends BroadcastReceiver {&lt;br /&gt; @Override&lt;br /&gt; public void onReceive(final Context context, final Intent bootintent) {&lt;br /&gt;  Intent mServiceIntent = new Intent();&lt;br /&gt;mServiceIntent.setAction("com.enea.training.bootdemo.BootDemoService");&lt;br /&gt;  context.startService(mServiceIntent);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;This component is basic and it will just create an intent to start our background service when it receives the boot completed intent.&lt;br /&gt;&lt;br /&gt;The service will create a Timer task to write to the log at a preset interval. Once it is started the timer task will be registered and the service will keep running in the background.&lt;br /&gt;&lt;pre&gt;package com.enea.training.bootdemo;&lt;br /&gt;&lt;br /&gt;import java.util.Timer;&lt;br /&gt;import java.util.TimerTask;&lt;br /&gt;&lt;br /&gt;import android.app.Service;&lt;br /&gt;import android.content.Intent;&lt;br /&gt;import android.os.IBinder;&lt;br /&gt;import android.util.Log;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Simple demo service that schedules a timer task to write something to &lt;br /&gt; * the log at regular intervals.&lt;br /&gt; * @author BMB&lt;br /&gt; *&lt;br /&gt; */&lt;br /&gt;public class BootDemoService extends Service {&lt;br /&gt; /**&lt;br /&gt;  * Delay until first exeution of the Log task.&lt;br /&gt;  */&lt;br /&gt; private final long mDelay = 0;&lt;br /&gt; /**&lt;br /&gt;  * Period of the Log task.&lt;br /&gt;  */&lt;br /&gt; private final long mPeriod = 500;&lt;br /&gt; /**&lt;br /&gt;  * Log tag for this service.&lt;br /&gt;  */ &lt;br /&gt; private final String LOGTAG = "BootDemoService";&lt;br /&gt; /**&lt;br /&gt;  * Timer to schedule the service.&lt;br /&gt;  */&lt;br /&gt; private Timer mTimer;&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * Implementation of the timer task.&lt;br /&gt;  */&lt;br /&gt; private class LogTask extends TimerTask {&lt;br /&gt;  public void run() {&lt;br /&gt;   Log.i(LOGTAG, "scheduled");&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; private LogTask mLogTask; &lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public IBinder onBind(final Intent intent) {&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public void onCreate() {&lt;br /&gt;  super.onCreate();&lt;br /&gt;  Log.i(LOGTAG, "created");&lt;br /&gt;  mTimer = new Timer();&lt;br /&gt;  mLogTask = new LogTask();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public void onStart(final Intent intent, final int startId) {&lt;br /&gt;  super.onStart(intent, startId);&lt;br /&gt;  Log.i(LOGTAG, "started");&lt;br /&gt;  mTimer.schedule(mLogTask, mDelay, mPeriod);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;There is one more important thing to consider for this simple demo application and that is to add the correct intent-filters to the Android.xml file. We need to register for the BOOT_COMPLETED intent but also for the intent that will start the actual service.&lt;br /&gt;&lt;pre&gt;&amp;lt ?xml version="1.0" encoding="utf-8"?&amp;gt&lt;br /&gt;&amp;lt manifest xmlns:android="http://schemas.android.com/apk/res/android"&lt;br /&gt;      package="com.enea.oresund.training.bootdemo"&lt;br /&gt;      android:versionCode="1"&lt;br /&gt;      android:versionName="1.0"&amp;gt&lt;br /&gt;      &amp;lt uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /&amp;gt&lt;br /&gt;    &amp;lt application android:icon="@drawable/icon" android:label="@string/app_name"&amp;gt&lt;br /&gt;       &amp;lt service android:name=".BootDemoService"&amp;gt&lt;br /&gt;       &amp;lt intent-filter&amp;gt&lt;br /&gt;       &amp;lt action&lt;br /&gt;       android:name = "com.enea.training.bootdemo.BootDemoService"&amp;gt&lt;br /&gt;       &amp;lt /action&amp;gt&lt;br /&gt;       &amp;lt /intent-filter&amp;gt&lt;br /&gt;       &amp;lt /service&amp;gt&lt;br /&gt;       &amp;lt receiver android:name=".BootDemoReceiver"&amp;gt&lt;br /&gt;       &amp;lt intent-filter&amp;gt&lt;br /&gt;       &amp;lt action&lt;br /&gt;       android:name ="android.intent.action.BOOT_COMPLETED"&amp;gt&lt;br /&gt;       &amp;lt /action&amp;gt&lt;br /&gt;       &amp;lt /intent-filter&amp;gt&lt;br /&gt;       &amp;lt /receiver&amp;gt&lt;br /&gt;    &amp;lt /application&amp;gt&lt;br /&gt;    &amp;lt uses-sdk android:minSdkVersion="3" /&amp;gt&lt;br /&gt;&amp;lt /manifest&amp;gt &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Summary - adding functionality at startup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With this post I think that we have covered the alternatives for adding functionality at some point during the boot process. To sum things up there is three possible places to do something like this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Modifying the init.rc script for native services &lt;/li&gt;&lt;li&gt;Modifying the system server to include a separate thread&lt;/li&gt;&lt;li&gt;Writing a standard Android service and register to launch it through the BOOT_COMPLETED intent&lt;/li&gt;&lt;/ol&gt;There may be other tricks you could use but they are more far-fetched. Unless you are building your own hardware or playing with the open source project for fun the third alternative is the only possible option. This is useful to register alarms or maybe an IM-client running in the background. &lt;br /&gt;I would however like to add a word of caution since running services in the background will take some resources from the system. Think carefully about if you really need to automatically launch your service every time the system has booted up. It may be better to let the user choose when to start your application in order to save some system resources.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-6534309724685427559?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/6534309724685427559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/09/starting-android-service-after-boot.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6534309724685427559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/6534309724685427559'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/09/starting-android-service-after-boot.html' title='Starting an Android service after boot'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-8612081740971440534</id><published>2009-08-28T09:55:00.001+02:00</published><updated>2009-08-28T09:56:10.942+02:00</updated><title type='text'>The init process and init.rc</title><content type='html'>In this post I will wrap up the analysis of what is going on at boot by looking at the Android init process and the init.rc file. If we start with the source you will find the code for the init process under /system/core/init in the source tree. The init process is what will set up all native services and this is similar to a regular Linux system boot. At this stage we are not executing in the actual android runtime. There is however some Android specifics going on already at this level. One example of this is that the init.rc script is written in a specific format called the Android init language. This is covered in the readme file that is kept in the same directory as the init source. Since I have not seen very much about it on the net though I will post some of the main concepts here. I will also give a small example on how to add your own native service at startup.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;The Android init language&lt;/span&gt;&lt;br /&gt;The language used by the init process has four classes of statements. These are actions, commands, services and options. Actions are associated to commands in the way that an action is a sequence of commands. An action also need something called a trigger in that the sequence of commands will be executed when the trigger event has occured. An exemple may look like:&lt;br /&gt;&lt;pre&gt;on boot&lt;br /&gt;ifup lo&lt;br /&gt;hostname localhost&lt;br /&gt;domainname localdomain&lt;br /&gt;&lt;/pre&gt;This action will run a command sequence to set up basic networking once it receives the boot trigger. The supported commands include export, chmod, chown and a few others. The complete list of available commands can be found in the readme file. &lt;br /&gt;Services are programs that are launched by init. They are associated with options which control how they are started. The syntax for starting a service is:&lt;br /&gt;service &amp;lt; name &amp;gt; &amp;lt; pathname &amp;gt; [&amp;lt; argument &amp;gt; ]*&lt;br /&gt;&amp;lt option &amp;gt&lt;br /&gt;&amp;lt option &amp;gt&lt;br /&gt;...&lt;br /&gt;There is a number of options available and a few of them are:&lt;br /&gt;&lt;b&gt;critical&lt;/b&gt; - &lt;i&gt;this is a critical process and init will restart the device if it exists more than four times in four minutes&lt;/i&gt;&lt;br /&gt;&lt;b&gt;user&lt;/b&gt; &amp;lt username &amp;gt - &lt;i&gt;change to this username before executing the service&lt;/i&gt;&lt;br /&gt;&lt;b&gt;group&lt;/b&gt; &amp;lt groupname &amp;gt [&amp;lt groupname &amp;gt ]* - &lt;i&gt;change to groupname before executing the service&lt;/i&gt;&lt;br /&gt;&lt;b&gt;setenv&lt;/b&gt; &amp;lt name &amp;gt &amp;lt value &amp;gt - &lt;i&gt; set environment variable &amp;lt name &amp;gt to &amp;lt value &amp;gt in the launched process &lt;/i&gt;&lt;br /&gt;The init script is also the place where some important system properties are set. This is done with the setprop command and include things like the memory thresholds for applications, tcp buffer sizes etc.&lt;br /&gt;The init.rc file itself is found in the root directory on a device and in the source tree it is kept under system/core/rootfs. The below example is the actual init.rc file that I have shortened significantly. The basic concepts are clearly illustrated. First there is an action on init where a long sequence of commands is run. As you can see it is accepted to use comments and they are preceded by #. A number of variables are setup during init and file systems are mounted. The next step is the boot action where networking is set up and properties assigned to the system. Then there is a list of services to be started by init.&lt;br /&gt;&lt;pre&gt;on init&lt;br /&gt;sysclktz 0&lt;br /&gt;loglevel 3&lt;br /&gt;# setup the global environment&lt;br /&gt;export PATH /sbin:/system/sbin:/system/bin:/system/xbin&lt;br /&gt;export LD_LIBRARY_PATH /system/lib&lt;br /&gt;export ANDROID_BOOTLOGO 1&lt;br /&gt;export ANDROID_ROOT /system&lt;br /&gt;...&lt;br /&gt;# mount mtd partitions&lt;br /&gt;1. &lt;br /&gt;Mount /system rw first to give the filesystem a chance to save a checkpoint&lt;br /&gt;mount yaffs2 mtd@system /system&lt;br /&gt;mount yaffs2 mtd@system /system ro remount&lt;br /&gt;2. &lt;br /&gt;We chown/chmod /data again so because mount is run as root + defaults&lt;br /&gt;mount yaffs2 mtd@userdata /data nosuid nodev&lt;br /&gt;chown system system /data&lt;br /&gt;chmod 0771 /data&lt;br /&gt;...&lt;br /&gt;on boot&lt;br /&gt;# basic network init&lt;br /&gt;ifup lo&lt;br /&gt;hostname localhost&lt;br /&gt;domainname localdomain&lt;br /&gt;# set RLIMIT_NICE to allow priorities from 19 to -20&lt;br /&gt;setrlimit 13 40 40&lt;br /&gt;# Define the oom_adj values for the classes of processes that can be&lt;br /&gt;# killed by the kernel. These are used in ActivityManagerService.&lt;br /&gt;setprop ro.FOREGROUND_APP_ADJ 0&lt;br /&gt;setprop ro.VISIBLE_APP_ADJ 1&lt;br /&gt;setprop ro.SECONDARY_SERVER_ADJ 2&lt;br /&gt;setprop ro.BACKUP_APP_ADJ 2&lt;br /&gt;setprop ro.HOME_APP_ADJ 4&lt;br /&gt;setprop ro.HIDDEN_APP_MIN_ADJ 7&lt;br /&gt;setprop ro.CONTENT_PROVIDER_ADJ 14&lt;br /&gt;setprop ro.EMPTY_APP_ADJ 15&lt;br /&gt;...&lt;br /&gt;## Daemon processes to be run by init.&lt;br /&gt;##&lt;br /&gt;service console /system/bin/sh&lt;br /&gt;console&lt;br /&gt;# adbd is controlled by the persist.service.adb.enable system property&lt;br /&gt;service adbd /sbin/adbd&lt;br /&gt;disabled&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;Starting your own service at boot.&lt;/span&gt;&lt;br /&gt;Normally there is not much need to do things in the init script and start services of your own. What is provided in the system goes a long way and often it may be better to add something to the Android runtime instead of using the native services. If you have a reason to add something or just what to try things out however it is relatively straight forward to add a native service to that init sequence. I have created a simple example that writes the time elapsed since it started to the log. It wakes up every three seconds. The code for exampleservice.c looks like:&lt;br /&gt;&lt;pre&gt;#define LOG_TAG "Example Service"&lt;br /&gt;#include &amp;lt; utils/log.h &amp;gt;&lt;br /&gt;#include &amp;lt; unistd.h &amp;gt;&lt;br /&gt;int main(int argc, char **argv)&lt;br /&gt;{&lt;br /&gt;    LOGI("Service started");&lt;br /&gt;    int elapsed = 0;&lt;br /&gt;    while(1)&lt;br /&gt;    {&lt;br /&gt;         sleep(3);&lt;br /&gt;         elapsed += 3;&lt;br /&gt;         LOGI("Service elapsed time is %d", elapsed);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Place this somewhere in the platform build system and build as an executable. The build system will place the output in the /system/bin folder on the device. Now all that is needed is to add the following to the init.rc script:&lt;br /&gt;&lt;pre&gt;service exampleservice /system/bin/exampleservice&lt;br /&gt;user exampleservice&lt;br /&gt;group exampleservice&lt;br /&gt;oneshot&lt;br /&gt;&lt;/pre&gt;and your service will start on init. It is also possible to write your own file using the Android init language that enables your services and variables. Then just add a line to import the file in init.rc and you are done.&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-8612081740971440534?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/8612081740971440534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/08/init-process-and-initrc.html#comment-form' title='32 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8612081740971440534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8612081740971440534'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/08/init-process-and-initrc.html' title='The init process and init.rc'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>32</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3968455742559023772</id><published>2009-08-25T23:41:00.003+02:00</published><updated>2009-08-26T00:18:09.703+02:00</updated><title type='text'>Back after the summer with some NDK comments</title><content type='html'>Time to pick up on the blog again after a summer where parts of the team have been on vacation and others have been hard at work in a couple of projects. In the mean time the Android platform has continued to evolve and a few things can be mentioned here:&lt;br /&gt;&lt;br /&gt;1. The kernel has been removed from the Android manifest file and now requires a separate git pull if you are interested in it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;git clone git://android.git.kernel.org/kernel/common.git&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will save some time when syncing the repo and since the kernel was built outside the Android build system anyway it makes sense to keep it separated.&lt;br /&gt;&lt;br /&gt;2. The NDK (Native Development Kit) was released allowing some support for native code in Android applications.&lt;br /&gt;Making it possible to use native functionality in applications have been on the wish list for a long time and this is the first step in that direction. The list of supported API:s is very short though. The NDK currently supports:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;libc (C library) headers&lt;/li&gt;&lt;li&gt;libm (math library) headers&lt;/li&gt;&lt;li&gt;JNI interface headers&lt;/li&gt;&lt;li&gt;libz (Zlib compression) headers&lt;/li&gt;&lt;li&gt;liblog (Android logging) header&lt;/li&gt;&lt;li&gt;A Minimal set of headers for C++ support&lt;/li&gt;&lt;/ul&gt;  A c library combined with math and some logging capabilities provide enough for a some powerful algorithm implementations but to be of broader interest some more API:s are probably necessary. Natural candidates would be graphics support (openGL) and maybe some codecs. Currently the NDK is a good way to experiment with native functionality without going through the hoops of learning all about the platform and build system. For some applications it may also be exactly what is needed.&lt;br /&gt;&lt;br /&gt;It looks like things will be picking up for the Android team during the fall and we aim to keep posting interesting tidbits here.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3968455742559023772?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3968455742559023772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/08/back-after-summer-with-some-ndk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3968455742559023772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3968455742559023772'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/08/back-after-summer-with-some-ndk.html' title='Back after the summer with some NDK comments'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3119463339929115120</id><published>2009-07-01T16:41:00.005+02:00</published><updated>2009-07-03T13:32:12.985+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>The System Server in Android</title><content type='html'>In this post I will add some more detail on the system server in Android. The system server is the core of the Android system and as described in the boot sequence post it is started as soon as Dalvik is initialized and running. The other system services will be running in the context of the System Server process. We will start by looking at the code that runs when the System Server starts. This code is found in the file frameworks/base/services/java/com/android/server/SystemServer.java (in the open source project tree) and we will start this discussion from the main entry point.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; /** &lt;br /&gt;     * This method is called from Zygote to initialize the system. This will cause the native &lt;br /&gt;     * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back&lt;br /&gt;     * up into init2() to start the Android services.&lt;br /&gt;     */ &lt;br /&gt;    native public static void init1(String[] args);&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        // The system server has to run all of the time, so it needs to be&lt;br /&gt;        // as efficient as possible with its memory usage.&lt;br /&gt;        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);&lt;br /&gt;        &lt;br /&gt;        System.loadLibrary("android_servers");&lt;br /&gt;        init1(args);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static final void init2() {&lt;br /&gt;        Log.i(TAG, "Entered the Android system server!");&lt;br /&gt;        Thread thr = new ServerThread();&lt;br /&gt;        thr.setName("android.server.ServerThread");&lt;br /&gt;        thr.start();&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first thing that happens is that the server will load a native library called android_servers that provides interfaces to native functionality. Source files for this lib are placed in frameworks/base/services/jni/. Then the native init method that will setup native services is called, init1(args), and executed. The name of the function that implements this is system_init() and the it resides in frameworks/base/cmds/system_server/library/system_init.cpp. After setting up the native services there is a callback:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;runtime-&gt;callStatic("com/android/server/SystemServer", "init2");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to init2() above to create the server thread. This thread will start the remaining services in the system according to the necessary start order. A snippet of the initial sequence gives:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; // Critical services...&lt;br /&gt;        try {&lt;br /&gt;            Log.i(TAG, "Starting Power Manager.");&lt;br /&gt;            power = new PowerManagerService();&lt;br /&gt;            ServiceManager.addService(Context.POWER_SERVICE, power);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Activity Manager.");&lt;br /&gt;            context = ActivityManagerService.main(factoryTest);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting telephony registry");&lt;br /&gt;            ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));&lt;br /&gt;&lt;br /&gt;            AttributeCache.init(context);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Package Manager.");&lt;br /&gt;            pm = PackageManagerService.main(context,&lt;br /&gt;                    factoryTest != SystemServer.FACTORY_TEST_OFF);&lt;br /&gt;&lt;br /&gt;            ActivityManagerService.setSystemProcess();&lt;br /&gt;&lt;br /&gt;            mContentResolver = context.getContentResolver();&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Content Manager.");&lt;br /&gt;            ContentService.main(context,&lt;br /&gt;                    factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting System Content Providers.");&lt;br /&gt;            ActivityManagerService.installSystemProviders();&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Battery Service.");&lt;br /&gt;            BatteryService battery = new BatteryService(context);&lt;br /&gt;            ServiceManager.addService("battery", battery);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Hardware Service.");&lt;br /&gt;            hardware = new HardwareService(context);&lt;br /&gt;            ServiceManager.addService("hardware", hardware);&lt;br /&gt;&lt;br /&gt;            // only initialize the power service after we have started the&lt;br /&gt;            // hardware service, content providers and the battery service.&lt;br /&gt;            power.init(context, hardware, ActivityManagerService.getDefault(), battery);&lt;br /&gt;&lt;br /&gt;            Log.i(TAG, "Starting Alarm Manager.");&lt;br /&gt;            AlarmManagerService alarm = new AlarmManagerService(context);&lt;br /&gt;            ServiceManager.addService(Context.ALARM_SERVICE, alarm);&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We see that the power manager is started first, followed by the activity manager and the other services. There are a lot more services started after these initial and if you are interested take look in the SystemServer.java file. Each service is running in a separate Dalvik thread in the SystemServer process. To give some info on the components making up the system server we may have look at it using the DDMS tool:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_fcXaF6gx74U/Skt-LUxMZSI/AAAAAAAAAB0/WsPol_qxwL4/s1600-h/SystemServer_threads.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 230px;" src="http://3.bp.blogspot.com/_fcXaF6gx74U/Skt-LUxMZSI/AAAAAAAAAB0/WsPol_qxwL4/s400/SystemServer_threads.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5353511315078669602" /&gt;&lt;/a&gt;&lt;br /&gt;We see that the main Android services such as the activity manager, package manager, alarm manager etc. are running in their separate threads but as parts of the system server process.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3119463339929115120?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3119463339929115120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/07/system-server-in-android.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3119463339929115120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3119463339929115120'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/07/system-server-in-android.html' title='The System Server in Android'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_fcXaF6gx74U/Skt-LUxMZSI/AAAAAAAAAB0/WsPol_qxwL4/s72-c/SystemServer_threads.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-5191303535286382916</id><published>2009-06-11T10:56:00.010+02:00</published><updated>2009-09-01T15:12:39.140+02:00</updated><title type='text'>The Android boot process from power on</title><content type='html'>Since mobile platforms and embedded systems has some differences compared to Desktop systems in how they initially start up and boot this post will discuss the initial boot stages of an Android phone in some detail. Since we have used the &lt;a href="http://www.beagleboard.org/"&gt;Beagle Board&lt;/a&gt; as reference in some previous examples any specifics here are related to a similar system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;1. Power on and boot ROM code execution&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_fcXaF6gx74U/SjD_U-yd5pI/AAAAAAAAABE/pvl-MD6yomE/s1600-h/Android_boot_1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://3.bp.blogspot.com/_fcXaF6gx74U/SjD_U-yd5pI/AAAAAAAAABE/pvl-MD6yomE/s320/Android_boot_1.png" alt="" id="BLOGGER_PHOTO_ID_5346053493605918354" border="0" /&gt;&lt;/a&gt;At power on the CPU will be in a state where no initializations have been done. Internal clocks are not set up and the only memory available is the internal RAM. When power supplies are stable the execution will start with the Boot ROM code. This is a small piece of code that is hardwired in the CPU ASIC. For more information on boot ROM and configurations study the initalization chapter in&lt;br /&gt;&lt;a href="http://focus.ti.com/dsp/docs/dspsupporttechdocsc.tsp?sectionId=3&amp;amp;tabId=409&amp;amp;abstractName=spruf98b"&gt;the Omap 3530 TRM&lt;/a&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A. The Boot ROM code will detect the boot media using a system register that maps to some physical balls on the asic. This is to determine where to find the first stage of the boot loader.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;B. Once the boot media sequence is established the boot ROM will try to load the first stage boot loader to internal RAM. Once the boot loader is in place the boot ROM code will perform a jump and execution continues in the boot loader.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;2. The boot loader&lt;/span&gt;&lt;br /&gt;The boot loader is a special program separate from the Linux kernel that is used to set up initial memories and load the kernel to RAM. On desktop systems the boot loaders are programs like GRUB and in embedded Linux&lt;a href="http://www.denx.de/wiki/U-Boot"&gt; uBoot&lt;/a&gt; is often the boot loader of choice. Device manufacturers often use their own proprietary boot loaders. The requirements on a boot loader for Linux running on an ARM system can be found in the Booting document under &lt;code&gt;/Documentation/arm&lt;/code&gt; in the kernel source tree.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_fcXaF6gx74U/SjEEUbVhVKI/AAAAAAAAABM/fk_GJqUgpJA/s1600-h/Android_boot_2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://2.bp.blogspot.com/_fcXaF6gx74U/SjEEUbVhVKI/AAAAAAAAABM/fk_GJqUgpJA/s320/Android_boot_2.png" alt="" id="BLOGGER_PHOTO_ID_5346058981647406242" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A. The first boot loader stage will detect and set up external RAM.&lt;/li&gt;&lt;li&gt;B. Once external RAM is available and the system is ready the to run something more significant the first stage will load the main boot loader and place it in external RAM.&lt;/li&gt;&lt;li&gt;C. The second stage of the boot loader is the first &lt;span style="font-style: italic;"&gt;major&lt;/span&gt; program that will run. This may contain code to set up file systems, additional memory, network support and other things. On a mobile phone it may also be responsible for loading code for the modem CPU and setting up low level memory protections and security options.&lt;/li&gt;&lt;li&gt;D. Once the boot loader is done with any special tasks it will look for a Linux kernel to boot. It will load this from the boot media (or some other source depending on system configuration) and place it in the RAM. It will also place some boot parameters in memory for the kernel to read when it starts up.&lt;/li&gt;&lt;li&gt;E. Once the boot loader is done it will perform a jump to the Linux kernel, usually some decompression routine, and the kernel assumes system responsibility.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;3. The Linux kernel&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;The Linux kernel starts up in a similar way on Android as on other systems. It will set up everything that is needed for the system to run. Initialize interrupt controllers, set up memory protections, caches and scheduling.&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_fcXaF6gx74U/SjEIXFQ8S5I/AAAAAAAAABU/nYhvsqrSly4/s1600-h/Android_boot_3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://4.bp.blogspot.com/_fcXaF6gx74U/SjEIXFQ8S5I/AAAAAAAAABU/nYhvsqrSly4/s320/Android_boot_3.png" alt="" id="BLOGGER_PHOTO_ID_5346063425308740498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A. Once the memory management units and caches have been initialized the system will be able to use virtual memory and launch user space processes.&lt;/li&gt;&lt;li&gt;B. The kernel will look in the root file system for the init process (found under system/core/init in the Android open source tree) and launch it as the initial user space process.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;4. The init process&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;The init process is the "grandmother" of all system processes. Every other process in the system will be launched from this process or one of its descendants.&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_fcXaF6gx74U/SjEKEXkWItI/AAAAAAAAABc/Q606dt72nXg/s1600-h/Android_boot_4.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://3.bp.blogspot.com/_fcXaF6gx74U/SjEKEXkWItI/AAAAAAAAABc/Q606dt72nXg/s320/Android_boot_4.png" alt="" id="BLOGGER_PHOTO_ID_5346065302827705042" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt; A. The init process in Android will look for a file called init.rc. This is a script that describes the system services, file system and other parameters that need to be set up. The init.rc script is placed in system/core/rootdir in the Android open source project.&lt;/li&gt;&lt;li&gt;B. The init process will parse the init script and launch the system service processes.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;5. Zygote and Dalvik&lt;/span&gt;&lt;br /&gt;The Zygote is launched by the init process and will basically just start executing and and initialize the Dalvik VM.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_fcXaF6gx74U/SjENewbDDgI/AAAAAAAAABk/IJ9Mh7KoKYo/s1600-h/Android_boot_5.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://2.bp.blogspot.com/_fcXaF6gx74U/SjENewbDDgI/AAAAAAAAABk/IJ9Mh7KoKYo/s320/Android_boot_5.png" alt="" id="BLOGGER_PHOTO_ID_5346069054711074306" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;6. The system server&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;The system server is the first java component to run in the system. It will start all the Android services such as telephony manager and bluetooth. Start up of each service is currently written directly into the run method of the system server. The system server source can be found in the file frameworks/base/services/java/com/android/server/SystemServer.java in the open source project.&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_fcXaF6gx74U/SjEPYccFA4I/AAAAAAAAABs/pxdUKXuke8k/s1600-h/Android_boot_6.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://2.bp.blogspot.com/_fcXaF6gx74U/SjEPYccFA4I/AAAAAAAAABs/pxdUKXuke8k/s320/Android_boot_6.png" alt="" id="BLOGGER_PHOTO_ID_5346071145290728322" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;7. Boot completed&lt;/span&gt;&lt;br /&gt;Added this part to the post on 20090831 since it is very useful and something I should not have left out from the beginning. Once the System Server is up and running and the system boot has completed there is a standard broadcast action called ACTION_BOOT_COMPLETED. To start your own service, register an alarm or otherwise make your application perform some action after boot you should register to receive this broadcast intent.&lt;br /&gt;&lt;br /&gt;The separate boot steps and possible places to add your own functionality are covered in more detail in separate posts.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-5191303535286382916?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/5191303535286382916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/06/android-boot-process-from-power-on.html#comment-form' title='36 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5191303535286382916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/5191303535286382916'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/06/android-boot-process-from-power-on.html' title='The Android boot process from power on'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_fcXaF6gx74U/SjD_U-yd5pI/AAAAAAAAABE/pvl-MD6yomE/s72-c/Android_boot_1.png' height='72' width='72'/><thr:total>36</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3026263904261469862</id><published>2009-04-27T15:42:00.005+02:00</published><updated>2009-04-27T15:48:45.912+02:00</updated><title type='text'>A closer look at the Android project build system part II</title><content type='html'>This is the second post on the build system where we will take a closer look at the Android.mk file and what options are available. An Android.mk file describes the build for any native module that should go in the platform. We will start by looking at the makefile for the external ping facility found in &lt;code&gt;external/ping&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ifneq ($(TARGET_SIMULATOR),true)&lt;br /&gt;&lt;br /&gt;LOCAL_PATH:= $(call my-dir)&lt;br /&gt;&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;LOCAL_SRC_FILES:= ping.c&lt;br /&gt;LOCAL_MODULE := ping&lt;br /&gt;LOCAL_STATIC_LIBRARIES := libcutils libc&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;br /&gt;endif  # TARGET_SIMULATOR != true&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first line is just a check if we are building for the (obsolete?) simulator. The next line sets the local path to the current directory (the directory of this Android.mk file). This is handled by a function called mydir that can be found in the definitions.mk file in the build system.&lt;br /&gt;&lt;br /&gt;The next step is to include a makefile that will clear all local variables with the line &lt;code&gt;include $(CLEAR_VARS)&lt;/code&gt;. CLEAR_VARS is set in the build configuration in &lt;code&gt;config.mk&lt;/code&gt; and will include the &lt;code&gt;clear_vars.mk&lt;/code&gt; file at this point. The main purpose of this include is to make sure that we do not use any local variables set by another module.&lt;br /&gt;&lt;br /&gt;After the two initial lines that basically prepares the build system to start with this module we set the build variables. These are&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;LOCAL_SRC_FILES - the source files that make up this module&lt;br /&gt;LOCAL_MODULE - the name of the module&lt;br /&gt;LOCAL_STATIC_LIBRARIES - libraries to statically link to this module&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since ping will be an executable command placed in /system/bin in the Android file system the make file for building an executable should be used. This done with the line:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are makefiles available in the build system that can be used to build a number of different types of module. To include them you may use one of the variables set in the &lt;code&gt;config.mk&lt;/code&gt; file. A few important ones are:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;BUILD_EXECUTABLE - Build an executable module&lt;br /&gt;BUILD_SHARED_LIBRARY - Build a shared library&lt;br /&gt;BUILD_STATIC_LIBRARY - Build a static library&lt;br /&gt;BUILD_PREBUILT - Add prebuilt components&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There is also a number of local variables that are recognized by the build system and that needs to be set in order to build your module.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;LOCAL_C_INCLUDES - path to include files needed by your module, e.g. ($KERNEL_HEADERS)&lt;br /&gt;LOCAL_CFLAGS - Any additional flags to pass to the compiler&lt;br /&gt;LOCAL_LDFLAGS - Any additional flags to pass to the linker&lt;br /&gt;LOCAL_SHARED_LIBRARIES - Shared libraries that the module directly links against&lt;br /&gt;LOCAL_SRC_FILES - The source files to compile&lt;br /&gt;LOCAL_STATIC_LIBRARIES - Static libraries to include in the module&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You may use one &lt;code&gt;Android.mk&lt;/code&gt; to build several items. It is possible to build both a library and an executable using the same makefile. To illustrate how to write a makefile for some native functionality we will look at another example. This makefile will build a shared library and an executable. It links to a couple of shared libraries in the system.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;LOCAL_PATH:= $(call my-dir)&lt;br /&gt;&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;#Name of target to build&lt;br /&gt;LOCAL_MODULE:= libmylibrary&lt;br /&gt;#Source files to compile&lt;br /&gt;LOCAL_SRC_FILES:= mysrcfile.c mysothersrcfile.c&lt;br /&gt;#The shared libraries to link against&lt;br /&gt;LOCAL_SHARED_LIBRARIES := libcutils&lt;br /&gt;#No special headers needed&lt;br /&gt;LOCAL_C_INCLUDES +=&lt;br /&gt;#Prelink this library, also need to add it to the prelink map&lt;br /&gt;LOCAL_PRELINK_MODULE := true&lt;br /&gt;include $(BUILD_SHARED_LIBRARY)&lt;br /&gt;&lt;br /&gt;#Clear variables and build the executable&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;LOCAL_MODULE:= myinfocmd&lt;br /&gt;LOCAL_SRC_FILES:= mycmdsrcfile.c&lt;br /&gt;include $(BUILD_EXECUTABLE)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The output of the build system is put in the out folder in the Android project. Build output is directed to a subfolder based on the product. A default build is for the generic product and will output everything target related to that folder. A shared library ends up in  &lt;code&gt;/out/target/product/generic/system/lib&lt;/code&gt;. In the same way an executable will end up in &lt;code&gt;/out/target/product/generic/system/bin&lt;/code&gt;. The object files and intermediates are kept in the obj folder. The root, system, and data folders will be used to generate the file system images needed for Android in the last build step.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3026263904261469862?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3026263904261469862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/04/closer-look-at-android-project-build_27.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3026263904261469862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3026263904261469862'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/04/closer-look-at-android-project-build_27.html' title='A closer look at the Android project build system part II'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3924617358621544923</id><published>2009-04-24T15:40:00.008+02:00</published><updated>2009-04-24T16:03:51.264+02:00</updated><title type='text'>A closer look at the Android project build system part I</title><content type='html'>In this two part post we will take a closer look at the structure of the build system for native functionality. The build system is based on make and resides in the build folder in the project. The first part will look at what is found in this folder while the second part discusses the Android.mk file and options.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;envsetup.sh&lt;/span&gt;&lt;br /&gt;There is one important file in build directory itself. That is the envsetup.sh file. This shell script contains a lot of functionality that is nice to have when working with Android. To invoke it type&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;. build/envsetup.sh&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;in the android root directory. This will allow you to use a number of new commands including:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;m - make from the top of the tree&lt;br /&gt;mm - builds all modules in the current directory&lt;br /&gt;cgrep - grep in all c-files&lt;br /&gt;jgrep - grep in all java-files&lt;br /&gt;mgrep - grep in all makefiles&lt;br /&gt;lunch - choose build target&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;These shell commands are very useful when working with the platform. Whether you are looking for something specific in a source file or you just want to build the current module for a test.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;build/target&lt;/span&gt;&lt;br /&gt;The target directory contains make configurations for different boards and products. The target directory is where new products can be added as needed by a hardware manufacturer. In the current release there is a generic product description, and sdk product and some other files. The available boards are the emulator, a generic board and the simulator.&lt;br /&gt;&lt;br /&gt;The board makefiles describe the hardware platform level and can be shared among a number of products. For example you can build both the generic product and the generic_with_google product to run on in the emulator.&lt;br /&gt;&lt;br /&gt;The makefiles for different products are listed in the file &lt;code&gt;AndroidProducts.h&lt;/code&gt;. To add a new product put the makefile in the build/target/product folder and add the product to &lt;code&gt;AndroidProduct.h&lt;/code&gt;. It is possible for product makefiles to inherit from each other to reduce the need for copying. The generic_with_google products inherits the generic product that inherits the core product to make up a three level product specification.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;build/core&lt;/span&gt;&lt;br /&gt;The core folder is the location of the build system files. These files are used to set up the build system and to build all the different modules as configured in the individual Android.mk files. The main.mk file is the entry point to the build system and it is this files that is included in the top level makefile in the project root directory. The build system can also be invoked by the shell command mm with at subset of the makefiles&lt;br /&gt;&lt;br /&gt;The include order and hierarchy of the makefiles is rather complicated but an attempt of illustration can be found in this figure.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_fcXaF6gx74U/SfHDQ7kZ0nI/AAAAAAAAAA8/Nds1vVnfrLw/s1600-h/make_files_overview.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 226px;" src="http://4.bp.blogspot.com/_fcXaF6gx74U/SfHDQ7kZ0nI/AAAAAAAAAA8/Nds1vVnfrLw/s320/make_files_overview.png" alt="" id="BLOGGER_PHOTO_ID_5328254529791709810" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Most of the build configuration is set in the &lt;code&gt;config.mk&lt;/code&gt; file and the &lt;code&gt;definitions.mk&lt;/code&gt; file contains the functions to be invoked for the different source types. In the above figure the build system is invoked to build a shared library. The Android makefile uses the &lt;code&gt;BUILD_SHARED_LIBRARY&lt;/code&gt; variable set in the &lt;code&gt;config.mk&lt;/code&gt; file. This will set the build chain for building a shared library in a number of steps using several other files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3924617358621544923?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3924617358621544923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/04/closer-look-at-android-project-build.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3924617358621544923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3924617358621544923'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/04/closer-look-at-android-project-build.html' title='A closer look at the Android project build system part I'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_fcXaF6gx74U/SfHDQ7kZ0nI/AAAAAAAAAA8/Nds1vVnfrLw/s72-c/make_files_overview.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-9170671040320091797</id><published>2009-04-01T10:44:00.007+02:00</published><updated>2009-04-02T10:05:36.278+02:00</updated><title type='text'>JNI hands on</title><content type='html'>In the demo setup at the &lt;acronym title="ENEA Android seminar, Mar 10th 2009"&gt;seminar&lt;/acronym&gt; we hijacked the SMS application to send a LINX signal using &lt;acronym title="Java Native Interfaces"&gt;JNI&lt;/acronym&gt;. In this post I'll describe more in detail how we implemented it.&lt;br /&gt;&lt;br /&gt;First you need to create a Java-class that loads the C-library and declares the method (&lt;code&gt;send(...)&lt;/code&gt;)&lt;br /&gt;&lt;pre&gt;public class NativeLib {&lt;br /&gt;    static {&lt;br /&gt;        try {&lt;br /&gt;            Log.i("JNI", "Trying to load libNativeLib.so");&lt;br /&gt;            System.loadLibrary("NativeLib");&lt;br /&gt;        }&lt;br /&gt;        catch (UnsatisfiedLinkError ule) {&lt;br /&gt;            Log.e("JNI", "WARNING: Could not load libNativeLib.so");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    public static native long send(String number, String message);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Call the method somewhere appropriate from your activity:&lt;br /&gt;&lt;pre&gt;long sum = NativeLib.send(...);&lt;/pre&gt;&lt;br /&gt;Next, you need to generate C-headers from the NativeLib Java-class:&lt;br /&gt;&lt;pre&gt;cd &amp;lt;path to eclipse project dir&amp;gt;/bin&lt;br /&gt;javah &amp;lt;class name&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Create a directory &lt;code&gt;nativelib&lt;/code&gt; in the &lt;code&gt;&amp;lt;android root&amp;gt;/external&lt;/code&gt; directory and move the header file to here. &lt;br /&gt;&lt;br /&gt;Now, implement the C-file (and remember to include your recently generated header-file)&lt;br /&gt;&lt;pre&gt;#include "com_android_mms_transaction_NativeSms.h"&lt;br /&gt;&lt;br /&gt;JNIEXPORT jlong JNICALL Java_com_android_mms_transaction_NativeSms_send&lt;br /&gt;  (JNIEnv *env, jclass class, jstring number, jstring message)&lt;br /&gt;{&lt;br /&gt;  //Get the native string from javaString&lt;br /&gt;  const char *numString;&lt;br /&gt;  const char *messageString;&lt;br /&gt;&lt;br /&gt;  numString = (*env)-&gt;GetStringUTFChars(env, number, 0);&lt;br /&gt;  messageString = (*env)-&gt;GetStringUTFChars(env, message, 0);&lt;br /&gt;&lt;br /&gt;  /*code to handle the sms info in native context goes here*/&lt;br /&gt;&lt;br /&gt;/*release resources when done*/&lt;br /&gt;  (*env)-&gt;ReleaseStringUTFChars(env, number, numString);  (*env)-&gt;ReleaseStringUTFChars(env, message, messageString);&lt;br /&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Next, we will construct a make-file: name it &lt;code&gt;Android.mk&lt;/code&gt; and put it in  &lt;code&gt;&amp;lt;android root&amp;gt;/external/nativelib&lt;/code&gt;. Fill it up with the following:&lt;br /&gt;&lt;pre&gt;LOCAL_PATH := $(call my-dir)&lt;br /&gt;&lt;br /&gt;include $(CLEAR_VARS)&lt;br /&gt;&lt;br /&gt;LOCAL_SRC_FILES := %lt;name of C-file%gt;&lt;br /&gt;&lt;br /&gt;LOCAL_SHARED_LIBRARIES := libcutils&lt;br /&gt;&lt;br /&gt;LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)&lt;br /&gt;&lt;br /&gt;LOCAL_MODULE := libNativeLib&lt;br /&gt;&lt;br /&gt;include $(BUILD_SHARED_LIBRARY)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Open file &lt;code&gt;prelink-linux-arm.map&lt;/code&gt; in &lt;code&gt;&amp;lt;android root&amp;gt;/build/core&lt;/code&gt; and add the row:&lt;br&gt;&lt;br /&gt;&lt;code&gt;libNativeLib.so 0x9F400000&lt;/code&gt;&lt;br&gt;&lt;br /&gt;under comment:&lt;br&gt;&lt;br /&gt;&lt;code&gt;# libraries for specific apps or temporary libraries&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This will add your library to the prelink map. Make sure that the address is not used by anything else.&lt;br /&gt;Now type &lt;code&gt;make&lt;/code&gt; in Android root dir to build. Hopefully everything goes well and voila! You have implemented your native C-library&lt;br /&gt;&lt;br /&gt;/Sebastian&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-9170671040320091797?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/9170671040320091797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/04/jni-hands-on.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/9170671040320091797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/9170671040320091797'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/04/jni-hands-on.html' title='JNI hands on'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-806171523404741586</id><published>2009-03-31T13:18:00.007+02:00</published><updated>2009-03-31T17:06:37.803+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='seminar'/><title type='text'>Android seminar in Lund</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_fcXaF6gx74U/SdH8ldrnnEI/AAAAAAAAAAs/HXu2QcBx1kk/s1600-h/blogpostimage.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 133px; height: 200px;" src="http://4.bp.blogspot.com/_fcXaF6gx74U/SdH8ldrnnEI/AAAAAAAAAAs/HXu2QcBx1kk/s200/blogpostimage.jpg" alt="" id="BLOGGER_PHOTO_ID_5319310355454204994" border="0"&gt;&lt;/a&gt;Our initial project in the Android team was to prepare a demo were we integrated the Enea message passing methods available in &lt;a href="http://sourceforge.net/projects/linx/"&gt;Linx&lt;/a&gt; with the Android platform. This demo was presented at our Android seminar in Lund, Sweden on March 10. The seminar was a success with more than 200 attendees from different companies in the wireless industry, among them ST Ericsson and Sony Ericsson. The breakfast session included a short presentation of embedded Linux in general as well as an overview of the Android mobile technology platform.&lt;br /&gt;&lt;br /&gt;Our demo setup is illustrated below. The hardware we used for this setup was a &lt;a href="http://beagleboard.org/"&gt;beagle board&lt;/a&gt; running Android using the patches made by &lt;a href="http://embinux.com/"&gt;Embinux&lt;/a&gt;. The Linx kernel modules and libraries were cross compiled for the platform and added to the Android init scripts. We also created some test libraries to handle the communication.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_fcXaF6gx74U/SdH80R4_bJI/AAAAAAAAAA0/AlCsNtCnApA/s1600-h/demobild_smsdemo_blog.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 158px;" src="http://4.bp.blogspot.com/_fcXaF6gx74U/SdH80R4_bJI/AAAAAAAAAA0/AlCsNtCnApA/s320/demobild_smsdemo_blog.png" alt="" id="BLOGGER_PHOTO_ID_5319310609987103890" border="0"&gt;&lt;/a&gt;&lt;br /&gt;The setup allowed a user to write and send an SMS via the standard Android SMS application. When the user press "send" we catch the number and message and call a native C-routine via Java Native Interfaces. This routine creates and sends a Linx signal to a Linux PC with a phone attached to the COM-port, acting as a modem.  Finally the message is sent via AT-commands.&lt;br /&gt;&lt;br /&gt;This way we created a demo that interacts with the real world and with a obvious effect!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-806171523404741586?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/806171523404741586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/03/android-seminar-in-lund.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/806171523404741586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/806171523404741586'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/03/android-seminar-in-lund.html' title='Android seminar in Lund'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_fcXaF6gx74U/SdH8ldrnnEI/AAAAAAAAAAs/HXu2QcBx1kk/s72-c/blogpostimage.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-8911162414367053151</id><published>2009-03-26T17:19:00.006+01:00</published><updated>2009-03-26T17:52:18.450+01:00</updated><title type='text'>Getting started with LINX on Android</title><content type='html'>Initial LINX tests on Android were made using a &lt;a href="http://www.beagleboard.org/"&gt;beagle board&lt;/a&gt; running Android with patches from &lt;a href="http://embinux.com/"&gt;Embinux&lt;/a&gt;. To get started with LINX the following steps are needed:&lt;br /&gt;Download the LINX source from &lt;a href="http://sourceforge.net/projects/linx"&gt;SourceForge&lt;/a&gt;. To get an initial cross compiled build we need a matchning kernel. Currently just pointing out the kernel in the Android distro will not work since LINX will produce some build errors. This should be checked and maybe fixed later on.&lt;br /&gt;The way we worked around was to compile LINX against a standard kernel with Android patches. In this case a 2.6.27 OMAP kernel. I.e the build command will look something like:&lt;br /&gt;&lt;pre&gt;cd &amp;lt;path&amp;gt;make ARCH=arm CROSS_COMPILE=&amp;lt;path&amp;gt;/arm-none-linux-gnu-eabi- KERNEL=&amp;lt;path&amp;gt;&lt;/pre&gt;&lt;br /&gt;At this point we took the generated kernel modules and copied them to a suitable place in the Android file system. The rest of LINX currently needs to be statically linked by adding -static to the makefile gcc options. This is because it is not built as part of the android build system and c library.  Then copy the binaries to the /system/bin library of Android.&lt;br /&gt;An ownership change is also needed to make the commands run on android&lt;br /&gt;&lt;pre&gt;sudo chown root.root &amp;lt;file&amp;gt;&lt;br /&gt;sudo chmod 777 &amp;lt;file&amp;gt;&lt;/pre&gt;&lt;br /&gt;After this it is just a matter of starting up android and doing insmods using the shell. Links can be created with mklink.&lt;br /&gt;&lt;br /&gt;/Mattias&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-8911162414367053151?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/8911162414367053151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/03/getting-started-with-linx-on-android.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8911162414367053151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/8911162414367053151'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/03/getting-started-with-linx-on-android.html' title='Getting started with LINX on Android'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-254432337824511900.post-3405499021628033686</id><published>2009-03-26T15:38:00.005+01:00</published><updated>2009-03-26T17:47:40.936+01:00</updated><title type='text'>Howto build sdk and plugin - copy'n'paste version</title><content type='html'>The following commands are needed when building your own sdk and eclipse plugin.&lt;br /&gt;In your homedir:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mkdir ~/repodir ~/plugindir ~/eclipse-android&lt;br /&gt;&lt;br /&gt;cd ~/repodir&lt;br /&gt;&lt;br /&gt;repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake&lt;br /&gt;&lt;br /&gt;repo sync&lt;br /&gt;&lt;br /&gt;source ./build/envsetup.sh&lt;br /&gt;&lt;br /&gt;lunch 1&lt;br /&gt;&lt;br /&gt;make&lt;br /&gt;&lt;br /&gt;ECLIPSE_HOME=~/eclipse-android&lt;br /&gt;&lt;br /&gt;./development/tools/eclipse/scripts/build_server.sh ~/plugindir&lt;br /&gt;&lt;br /&gt;make sdk&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The output files are:&lt;br /&gt;~/plugindir/android-eclipse-v200903261355.zip (or whatever date it is)&lt;br /&gt;~/repodir/out/host/linux-x86/sdk/android-sdk_eng.user_linux-x86.zip (replace 'user' with your username)&lt;br /&gt;&lt;br /&gt;Not much info about what they do at the moment. Execute the commands in the specified order and it should work. If it doesn't - please comment and I will try to clarify.&lt;br /&gt;/Robert&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/254432337824511900-3405499021628033686?l=www.androidenea.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.androidenea.com/feeds/3405499021628033686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.androidenea.com/2009/03/howto-build-sdk-and-plugin-copynpaste.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3405499021628033686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/254432337824511900/posts/default/3405499021628033686'/><link rel='alternate' type='text/html' href='http://www.androidenea.com/2009/03/howto-build-sdk-and-plugin-copynpaste.html' title='Howto build sdk and plugin - copy&apos;n&apos;paste version'/><author><name>Enea Android Team</name><uri>http://www.blogger.com/profile/10157781734855979907</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
