tag:blogger.com,1999:blog-84342647907611865932024-03-10T12:13:22.635-07:00Malachi's AndroidAndroid Tips/Tricks and TutorialsMalachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.comBlogger93125tag:blogger.com,1999:blog-8434264790761186593.post-5632462882592414752017-04-27T18:43:00.001-07:002017-04-27T18:43:48.858-07:00Screen flashing after upgradeI finally got around to upgrading this (now old) machine from 16.04 -> 17.10 over the last couple days. After fighting with DKMS it's finally booting and working... except the screen keeps flashing.<br />
<br />
Why am I facing <a href="https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/269904" target="_blank">this</a> reportedly fixed bug?<br />
<br />
I managed to fix it by going into the NVidia X Server Settings and turning off this flag:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqYAyAAn2f5G33jXeRQHkd5tqsbtiFjGJaFXC7k6qYk8UaFsfYsbvBK1VR3qHRUUz_zXXYX7iCgVyJpX3uF0re6CCXyPHgU3fQVE_YvqbxuURN7Aw8g9Xve_WIHz4WJpA8l7XUJP19RfJQ/s1600/nvidia_settings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqYAyAAn2f5G33jXeRQHkd5tqsbtiFjGJaFXC7k6qYk8UaFsfYsbvBK1VR3qHRUUz_zXXYX7iCgVyJpX3uF0re6CCXyPHgU3fQVE_YvqbxuURN7Aw8g9Xve_WIHz4WJpA8l7XUJP19RfJQ/s1600/nvidia_settings.png" /></a></div>
<br />
As soon as I unchecked that, everything was fine.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-79731417675493358242016-04-22T14:33:00.000-07:002016-04-22T14:33:04.955-07:00Ubuntu upgrade - left mouse click failureI let Ubuntu upgrade to 16.04 today. Afterwards, the mouse would move, right-click worked, and left-click worked in some apps. Most notably it did not work on the system menu/notification bar. Doesn't even work on the login UI.<br />
<br />
I knew this happened last time too, but couldn't remember why. I finally figured it out.<br />
<br />
In Firefox, go into Settings, turn off chat. Reboot (I know, shouldn't have to do that, but I had to). Now, mouse works. Go back in and turn it back on, and it's still fine.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-34844767999762019582016-04-13T09:02:00.000-07:002016-04-13T09:02:26.756-07:00Unable to connect ADB to CM10As an Android developer, I have a ton of spare devices running various versions of Android. One of them is the original Samsung Galaxy Note running CM10 so that I can test backward compat with 4.x.<br />
<br />
Unfortunately, I have been unable to connect to it via adb/mtp/mass_storage for quite some time. adb via wifi works, but is dog slow when running connectedCheck.<br />
<br />
Luckily, I figured out how to fix it yesterday (and thus the reason I am leaving this post so I can find it in a years time when I forget yet again).<br />
<br />
It's completely incompatible with USB hubs. While all my other devices are plugged in through a single hub so that I can test on multiple devices, this CM10 device requires that I plug it in directly. Once I did that, it started working normally.<br />
<br />
Why didn't I think of that earlier? Did I mention that none of the other devices have this problem? Just the CM10 device.<br />
<br />Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-30331532556073719922015-11-12T20:39:00.001-08:002015-11-12T20:44:10.015-08:00Tag Heuer - Day 1<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhrz7XFLD_j0zrBPvTZQbga3WhPMZh5f_4D1XujFY_WkmNueN-_6OTaS7i16HzY9RyhPH_YhBvkxVg6E-9ZOuRufHY66_hL0LEyANJfWFqT7xzBJlFebRaS18rd3MmLQQwAlTmrciyHUc6/s1600/tag-small.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhrz7XFLD_j0zrBPvTZQbga3WhPMZh5f_4D1XujFY_WkmNueN-_6OTaS7i16HzY9RyhPH_YhBvkxVg6E-9ZOuRufHY66_hL0LEyANJfWFqT7xzBJlFebRaS18rd3MmLQQwAlTmrciyHUc6/s320/tag-small.jpg" width="292" /></a></div>
<div dir="ltr">
Ordering the watch was a little tricky. Every time I went to checkout, it would remove the watch from my cart. It was just minutes after the release, so I assumed the website was having a hard time. Since there were no local shops that were going to carry it, I decided to try one more thing. I created an account first and voila the order went through with no problems. That was Monday.</div>
<div dir="ltr">
Tuesday, they inform me it will be delivered by the following morning. It arrived before 10am Wednesday morning.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
The packaging was really well done. Not only secure, but even the packing slip was inside a thank you note. There was no instruction manual or anything - but I mean, really, those get out of date as fast as you OTA... And I had two of those right away.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
The magnetic charging base is nice, though it is awkward to use since it can't sit flat while charging.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
I've had the email address for years so I rather quickly disabled wear notifications from gmail. </div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
The first time my phone rang, I found myself glance at my watch first. That actually surprised me. I tried answering a call with the watch, but that was pretty pointless since it was still using the speaker and microphone from the phone a few feet away.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
It's rather comfortable. I like that Google Fit can be more accurate than before ( didn't always carry my phone while waking around the house, using elliptical, etc ). </div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
After charging through the night, today was the real test. After about 15 hours it is reporting 8% battery left. That's a far cry from 25 hours. It's a good thing I didn't leave gmail notifications enabled or I might have had to charge it after 5. I'd say the battery is the only downside so far.</div>
Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0Gladstone, Gladstone45.380676 -122.59481tag:blogger.com,1999:blog-8434264790761186593.post-89185094739373186222015-11-08T22:50:00.001-08:002015-11-08T22:50:35.306-08:00LG v10 Day 1<p dir="ltr">I've been using the LG v10 for about a day so far, an upgrade from my HTC One m7 GPe. </p>
<p dir="ltr">Overall, it's a nice device. A bit big, but I should be able to get used to that since I used to have the first gen Galaxy Note.</p>
<p dir="ltr">The UI is a little different... In the app drawer, there is a Google subfolder. You can add additional apps to it, but can't sort them. Actually doesn't look like you can remove them either. Haven't found any way to add additional folders yet. I was able to hide all the AT&T bloatware, so that's something.</p>
<p dir="ltr">Second screen? Eh still haven't decided if it is gimmick or useful. I didn't buy it for that feature anyway.</p>
<p dir="ltr">I was going to replace the launcher with the Google Now launcher, but I like that it is a doubly linked list so I'll keep it for now.</p>
<p dir="ltr">I do like that there it's a dedicated button for screenshots - the HTC was notorious for making me try try again. I also like that I can change the soft buttons ( order and content ).</p>
<p dir="ltr">I do not like the buttons on the back. I'm sure I'll get used to them, but whoever thought it was a good idea to encourage people to accidentally put their finger on the camera lens repeatedly was obviously not a photo buff.</p>
<p dir="ltr">I haven't run any cpu or ui benchmarks yet, but it seems rather quick. Speedtest wasn't looking great. Time will tell.</p>
<p dir="ltr">And in case you are wondering why I went with this phone, it was mostly because I wanted to try out the manual camera mode. I don't expect it to beat out my Canon, but it seemed i interesting. Also, removable battery and sd are hard to come by these days.</p>
Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0Gladstone, Gladstone45.380676 -122.59481tag:blogger.com,1999:blog-8434264790761186593.post-28743111970539851112015-10-28T23:18:00.000-07:002015-10-28T23:18:04.473-07:00USB3 hub disconnecting - dropping adb connection<br />
I'm probably jumping the gun, but I am hopeful.<br />
<br />
I was having a problem where my new <a href="http://www.skivatech.com/powerflow-octofire-8port-hub" target="_blank">OctoFire hub</a> was <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1371233" target="_blank">disconnecting quite often</a> -- especially if using something like Android ScreenMonitor.<br />
<br />
I think it is fixed. I found the suggestion to disable the autosuspend <a href="http://unix.stackexchange.com/questions/91027/how-to-disable-usb-autosuspend-on-kernel-3-7-10-or-above" target="_blank">here</a>.<br />
<br />
Edit the <span style="font-family: "Courier New",Courier,monospace;">/etc/default/grub</span> file and append to the <span style="font-family: "Courier New",Courier,monospace;">GRUB_CMDLINE_</span><wbr></wbr><span style="font-family: "Courier New",Courier,monospace;">LINUX_DEFAULT</span> line:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">usbcore.</span><wbr></wbr><span style="font-family: "Courier New",Courier,monospace;">autosuspend=</span><wbr></wbr><span style="font-family: "Courier New",Courier,monospace;">-1</span></blockquote>
Then run: <br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">sudo update-grub<br />
sudo reboot</span></blockquote>
Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-26353210605234481302014-09-16T11:08:00.000-07:002014-09-16T11:10:31.049-07:00ThreadingI was just thinking today....<br />
<br />
<ul>
<li><b>synchronized:</b> The single line open at the DMV</li>
<li><b>thread pool: </b>Cashiers at the grocery store</li>
<li><b>reentrant read/write locks: </b>The tiny booths at Saturday Market</li>
<li><b>volatile: </b>The "in-use" sign on airplane restrooms</li>
<li><b>concurrent collections: </b>Open-air Farmers Market</li>
<li><b>FIFO: </b>freeway on-ramp</li>
<li><b>LIFO: </b>UHaul Boxes</li>
</ul>
<br />
<br />
anyone else want to contribute some? Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-1715293380432029322014-08-20T11:33:00.000-07:002014-08-20T11:33:31.155-07:00nVidia + video tearing in my IDEI have been having some problems for the last few months where the
menu items in my IDEs (plural) were tearing. Sometimes they wouldn't
popup, sometimes more than one would be highlighted, etc.<br />
<br />
I found <a href="http://sn0v.wordpress.com/2012/01/09/solve-video-tearing-on-nvidia-gnome-3/" target="_blank">this article</a>
from 2 years ago which I couldn't really follow to the letter. My nv
only had one of the specified settings. I don't have ccsm installed,
etc.<br />
<br />
The ONLY change I made was:<br />
<br />
<ol>
<li><span style="font-family: "Courier New",Courier,monospace;">sudo su - root</span></li>
<li><span style="font-family: "Courier New",Courier,monospace;">echo CLUTTER_PAINT=disable-clipped-redraws:disable-culling >> /etc/environment</span></li>
<li>reboot</li>
</ol>
<br />
So far it seems to be working fine.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-36331441707853622572014-08-16T12:21:00.001-07:002014-08-16T19:06:15.849-07:00Writing a custom Gradle plugin: Java + buildSrc/I spent some time looking around at various suggestions (including on the Gradle documentation page) about how to write a custom plugin. For my specific purpose, it was not intended to be a shared plugin - but rather one to abstract out some of the logic we are doing in our build. I did <a href="http://malsandroid.blogspot.com/2014/08/writing-custom-gradle-plugin-groovy.html" target="_blank">another post on writing a Groovy plugin</a>, here's the Java one.<br />
<br />
To show that we are really doing a minimalist design here, let's start with a completely empty directory.<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">~> mkdir mytest</span><br /><span style="font-family: "Courier New",Courier,monospace;">~> cd mytest</span></span></blockquote>
<br />
<h2>
1. Gradle Wrapper</h2>
<br />
I personally use the Gradle Wrapper. Since the last post, I upgraded to
Gradle 2.0, but the Gradle Wrapper it installs by default is not
currently compatible with the Android plugin. As such, we'll still manually define one.<br />
<br />
Create a build.gradle file:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">task wrapper(type: Wrapper) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> gradleVersion = '1.12'</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></blockquote>
<br />
Run it.<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">~/mytest> gradle wrapper</span></blockquote>
<br />
Now that we have the wrapper installed in a fresh directory, let's look to that plugin. We'll be adding 3 Java classes and 1 properties file. <br />
<br />
Here's what we are aiming for:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">.</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">├── build.gradle</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">├── buildSrc</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── src</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── main</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ ├── java</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ └── org</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ └── eoti</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ └── gradle</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ ├── BrewinPluginExtension.java</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ ├── BrewinPlugin.java</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ │ └── BrewTask.java</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── resources</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── META-INF</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── gradle-plugins</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── brewin.properties</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">├── gradle</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── wrapper</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ ├── gradle-wrapper.jar</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">│ └── gradle-wrapper.properties</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">├── gradlew</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">└── gradlew.bat</span></span></blockquote>
<br />
<br />
<h2>
2. POJO Extension</h2>
<br />
Let's start this time by defining our POJO. We'll create <span style="font-family: "Courier New",Courier,monospace;">buildSrc/src/main/java/org/eoti/gradle/BrewinPluginExtension.java</span>.<br />
<br />
We'll add our package:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;</span></blockquote>
<br />
And import the Gradle API:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.*;</span></blockquote>
<br />
And create our POJO with getters/setters. <br />
<br />
Our complete POJO:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.*;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">public class BrewinPluginExtension</span><br />
<span style="font-family: "Courier New",Courier,monospace;">{</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> private String message = "Wake up!";</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> public String getMessage(){return message;}</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> public void setMessage(String message){this.message = message;}</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></blockquote>
<br />
<h2>
3. Task</h2>
<br />
Next, we'll define our task. Create <span style="font-family: "Courier New",Courier,monospace;">buildSrc/src/main/java/org/eoti/gradle/BrewTask.java</span>.<br />
<br />
We'll add our package and imports:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;<br /><br />import org.gradle.api.*;<br />import org.gradle.api.tasks.*;</span><br />
<br />
Our class will extend <span style="font-family: "Courier New",Courier,monospace;">DefaultTask</span>.<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">public class BrewTask extends DefaultTask{...}</span></blockquote>
<br />
Next we'll define our task and annotate it:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">@TaskAction</span><br />
<span style="font-family: "Courier New",Courier,monospace;">public void brew() {...}</span></blockquote>
<br />
In the implementation, we want to find our configuration. If there isn't one, we'll create a default one. Then, we'll output our message. The complete code:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.*;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.tasks.*;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">public class BrewTask extends DefaultTask</span><br />
<span style="font-family: "Courier New",Courier,monospace;">{</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> @TaskAction</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> public void brew() {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> BrewinPluginExtension extension = getProject().getExtensions().findByType(BrewinPluginExtension.class);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> if(extension == null)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> extension = new BrewinPluginExtension();</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> </span><br />
<span style="font-family: "Courier New",Courier,monospace;"> System.out.format("%s\n", extension.getMessage());</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></blockquote>
<br />
Note the <span style="font-family: "Courier New",Courier,monospace;">getMessage()</span> that we defined in our POJO.<br />
<br />
<h2>
4. Plugin</h2>
<br />
Next, we'll define our plugin. Create <span style="font-family: "Courier New",Courier,monospace;">buildSrc/src/main/java/org/eoti/gradle/BrewinPlugin.java</span>.<br />
<br />
Add your package and the Gradle import. In my case, that is:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.*;</span></blockquote>
<br />
Our class <span style="font-family: "Courier New",Courier,monospace;">implements Plugin<Project><project></project></span> which means we have:<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<blockquote>
<span style="font-family: "Courier New",Courier,monospace;">@Override</span><br />
<span style="font-family: "Courier New",Courier,monospace;">public void apply(Project project){ ... }</span></blockquote>
<br />
We will specify two things in this function.<br />
<br />
First, an extension to allow parameters to be passed in:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">project.getExtensions().create("brewin", BrewinPluginExtension.class);</span></blockquote>
<br />
The name <span style="font-family: "Courier New",Courier,monospace;">"brewin"</span> is the name of the configuration block.<br />
<br />
Second, a task to be added once this plugin is applied:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">project.getTasks().create("brew", BrewTask.class);</span></blockquote>
<br />
That <span style="font-family: "Courier New",Courier,monospace;">'brew'</span> is the <span style="font-family: "Courier New",Courier,monospace;">@TaskAction</span> name from above.<br />
<br />
The complete plugin:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">package org.eoti.gradle;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">import org.gradle.api.*;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"></span><br />
<span style="font-family: "Courier New",Courier,monospace;">public class BrewinPlugin implements Plugin<project></project></span><br />
<span style="font-family: "Courier New",Courier,monospace;">{</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> @Override</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> public void apply(Project project)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> project.getExtensions().create("brewin", BrewinPluginExtension.class);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> project.getTasks().create("brew", BrewTask.class);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></blockquote>
<br />
<br />
<h2>
5. Properties</h2>
<br />
Now, we need to add the properties file using the same configuration name we chose above. In this case, <span style="font-family: "Courier New",Courier,monospace;">buildSrc/src/main/resources/META-INF/gradle-plugins/brewin.properties</span>.<br />
<br />
It contains one line that points to our plugin implementation:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">implementation-class=org.eoti.gradle.BrewinPlugin</span></blockquote>
<br />
Ok, we're almost done.<br />
<br />
<h2>
6. Apply it</h2>
<br />
In your top-level <span style="font-family: "Courier New",Courier,monospace;">build.gradle</span>, specify that we want to apply our new plugin by adding this to the top:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">apply plugin: org.eoti.gradle.BrewinPlugin</span></blockquote>
<br />
And then from the command line, call the task we defined earlier:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">~/mytest> ./gradlew brew</span></blockquote>
<br />
<br />
That's great! But, why did we create a configuration parameter if we aren't going to use it?<br />
<br />
Add this to your top-level <span style="font-family: "Courier New",Courier,monospace;">build.gradle</span>:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">brewin{</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> message = "Make another pot!"</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></blockquote>
<br />
And then re-run it:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">~/mytest> ./gradlew brew</span></blockquote>
<br />
There you go. You can add additional parameters, additional Java logic, etc.<br />
<br />Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com2tag:blogger.com,1999:blog-8434264790761186593.post-80072513283880200382014-08-16T00:32:00.000-07:002015-11-06T22:58:47.507-08:00Writing a custom Gradle plugin: Groovy + buildSrc/I spent some time looking around at various suggestions (including on the Gradle documentation page) about how to write a custom plugin. For my specific purpose, it was not intended to be a shared plugin - but rather one to abstract out some of the logic we are doing in our build. I'll probably actually do <a href="http://malsandroid.blogspot.com/2014/08/writing-custom-gradle-plugin-java.html" target="_blank">another post on writing a Java plugin</a>, but for now let's try the Groovy one.<br />
<br />
To show that we are really doing a minimalist design here, let's start with a completely empty directory.<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">~> mkdir mytest</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">~> cd mytest</span></blockquote>
<br />
I personally use the Gradle Wrapper. Gradle 1.6 is installed on the system, but once the Gradle Wrapper takes over it's ignored.<br />
<br />
Create a <span style="font-family: "courier new" , "courier" , monospace;">build.gradle</span> file:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">task wrapper(type: Wrapper) {<br /> gradleVersion = '1.12'<br />}</span></blockquote>
<br />
Run it.<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">~/mytest> gradle wrapper</span></blockquote>
<br />
Now that we have the wrapper installed in a fresh directory, let's look to that plugin. We'll be adding 1 groovy file and 1 properties file.<br />
<br />
Here's what we are aiming for:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">.<br />├── build.gradle<br />├── buildSrc<br />│ └── src<br />│ └── main<br />│ ├── groovy<br />│ │ └── GroovinPlugin.groovy<br />│ └── resources<br />│ └── META-INF<br />│ └── gradle-plugins<br />│ └── groovin.properties<br />├── gradle<br />│ └── wrapper<br />│ ├── gradle-wrapper.jar<br />│ └── gradle-wrapper.properties<br />├── gradlew<br />└── gradlew.bat</span></span></blockquote>
<br />
In <span style="font-family: "courier new" , "courier" , monospace;">buildSrc/src/main/groovy/</span> create your new plugin file. In my case, it was called <span style="font-family: "courier new" , "courier" , monospace;">GroovinPlugin.groovy</span>.<br />
<br />
We'll still put a Java-style package at the top, even though the source file was not contained in a Java-style package directory. IE: I used package <span style="font-family: "courier new" , "courier" , monospace;">org.eoti.gradle</span> even though the directory was not <span style="font-family: "courier new" , "courier" , monospace;">org/eoti/gradle</span>.<br />
<br />
We need to import the Gradle API.<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">import org.gradle.api.*<br />import org.gradle.api.plugins.*</span></blockquote>
<br />
Our class (same name as the file) <span style="font-family: "courier new" , "courier" , monospace;">implements Plugin<Project><project><project></project></project></span> which means we have:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">void apply(Project project) { ... }</span></blockquote>
<br />
In my case I specified two things in this function.<br />
<br />
First, an extension to allow parameters to be passed in:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">project.extensions.create("groovin", GroovinPluginExtension)</span></blockquote>
<br />
We'll discuss that <span style="font-family: "courier new" , "courier" , monospace;">GroovinPluginExtension</span> in a moment. The name <span style="font-family: "courier new" , "courier" , monospace;">"groovin" </span>is the name of the configuration block.<br />
<br />
Secondly, I specified a task to be added once this plugin is applied:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">project.task('groove') << {<br /> println project.groovin.message<br />}</span></blockquote>
<br />
That <span style="font-family: "courier new" , "courier" , monospace;">'groovin'</span> is the configuration name from above. <span style="font-family: "courier new" , "courier" , monospace;">'message' </span>is the parameter name defined inside <span style="font-family: "courier new" , "courier" , monospace;">GroovinPluginExtension</span>. The <span style="font-family: "courier new" , "courier" , monospace;">GroovinPluginExtension</span> is just another class defined in the same file (not an inner class though) providing a POGO. A POGO is basically a POJO that automatically creates the getters and setters for you.<br />
<br />
In this case, we define a <span style="font-family: "courier new" , "courier" , monospace;">String</span> called <span style="font-family: "courier new" , "courier" , monospace;">'message'</span>, as such:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">class GroovinPluginExtension {<br /> def String message = 'We be groovin\''<br />}</span></blockquote>
<br />
Put all together, the <span style="font-family: "courier new" , "courier" , monospace;">GroovinPlugin.groovy</span> looks like:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">package org.eoti.gradle;</span><br />
<span style="font-size: small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">import org.gradle.api.*</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">import org.gradle.api.plugins.*</span><br />
<span style="font-size: small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">class GroovinPlugin implements Plugin<Project><project> {</project></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> void apply(Project project) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> project.extensions.create("groovin", GroovinPluginExtension)</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> project.task('groove') << {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> println project.groovin.message</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">}</span><br />
<span style="font-size: small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">class GroovinPluginExtension {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;"> def String message = 'We be groovin\''</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">}</span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"></span></span></blockquote>
<br />
Pretty small, right?<br />
<br />
Now, we need to add the properties file using the same configuration name we chose above. In this case, <span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">buildSrc/src/main/resources/META-INF/gradle-plugins/<i><b>groovin</b></i>.properties</span>.</span><br />
<br />
It contains one line that points to our plugin implementation:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">implementation-class=org.eoti.gradle.GroovinPlugin</span></blockquote>
<br />
Ok, we're almost done.<br />
<br />
In your top-level <span style="font-family: "courier new" , "courier" , monospace;">build.gradle</span>, specify that we want to apply our new plugin by adding this to the top:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">apply plugin: org.eoti.gradle.GroovinPlugin</span></blockquote>
<br />
And then from the command line, call the task we defined earlier:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">~/mytest> ./gradlew groove</span></blockquote>
<br />
That's great! But, why did we create a configuration parameter if we aren't going to use it?<br />
<br />
Add this to your top-level <span style="font-family: "courier new" , "courier" , monospace;">build.gradle</span>:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">groovin{<br /> message = "We be jammin'"<br />}</span></blockquote>
<br />
And then re-run it:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: small;">~/mytest> ./gradlew groove</span></blockquote>
<br />
There you go. You can add additional parameters, additional Groovy logic, etc.<br />
<br />
<br />
<br />Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com3tag:blogger.com,1999:blog-8434264790761186593.post-71067469620944124232013-07-11T10:58:00.000-07:002013-07-11T10:58:10.789-07:00Changing the Wallpaper to Scaled in Ubuntu 13.04After upgrading to Ubuntu 13.04, I lost the ability to scale the
desktop background. At first, I tried just saving the image at a
different size, but it kept cropping it in ways I didn't like.<br />
<br />
Solution was pretty simple (though it should have still been available in the UI):<br />
<br />
<blockquote class="tr_bq">
<pre class="prettyprint"><code><span class="pln">gsettings </span><span class="kwd">set</span><span class="pln"> org</span><span class="pun">.</span><span class="pln">gnome</span><span class="pun">.</span><span class="pln">desktop</span><span class="pun">.</span><span class="pln">background picture</span><span class="pun">-</span><span class="pln">options </span><span class="str">"scaled"</span></code></pre>
</blockquote>
Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-62572097921238267252013-06-03T23:59:00.001-07:002013-06-03T23:59:08.534-07:00Unable to open MTP device '[usb:003,021]'Recently I upgraded my Samsung Galaxy Note to JellyBean. Around the same time, I also upgraded both the desktop and laptop to Raring Ringtail. When connecting the device to the dev boxes, the laptop continued to work. The desktop however would give me a never ending loop of popups like this one:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">Unable to open MTP device '[usb:003,021]'</span></span></blockquote>
<br />
While trying to resolve it, I found <a href="http://forum.xda-developers.com/showthread.php?t=2223401" target="_blank">this fix</a> about the ASUS Transformer...<br />
<br />
I followed the same instructions with a few slight tweaks...<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">/etc/udev/rules.d/51-android.rules</span>:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># MTP Settings added by Malachi</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># From dmesg:</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 166.765498] usb 3-4: reset high-speed USB device number 20 using ehci-pci</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 166.845468] usb 3-4: USB disconnect, device number 20</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.084889] usb 3-4: new high-speed USB device number 21 using ehci-pci</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.219607] usb 3-4: New USB device found, idVendor=04e8, idProduct=6860</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.219609] usb 3-4: New USB device strings: Mfr=2, Product=3, SerialNumber=4</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.219611] usb 3-4: Product: SAMSUNG-SGH-I717</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.219613] usb 3-4: Manufacturer: samsung</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"># [ 167.219614] usb 3-4: SerialNumber: 2a4c2c04</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">ENV{ID_MODEL}=="SAMSUNG-SGH-I717", ENV{ID_MODEL_ID}=="6860", ACTION=="add", RUN+="/usr/bin/sudo -b -u malachi /usr/bin/go-mtpfs -allow-other=true /media/SGH-I717"</span></span><br /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">ENV{ID_MODEL}=="SAMSUNG-SGH-I717", ENV{ID_MODEL_ID}=="6860", ACTION=="remove", RUN+="/bin/umount /media/SGH-I717"</span></span></blockquote>
<br />
in <span style="font-family: "Courier New",Courier,monospace;">/etc/fstab</span>:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">DeviceFs(SAMSUNG-SGH-I717) /media/SGH-I717 fuse.DeviceFs(SAMSUNG-SGH-I717) allow_other,rw,user,noauto 0 0</span></span></blockquote>
<br />
Now, when I connect, I get about 50 popups but then ADB works again.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com7tag:blogger.com,1999:blog-8434264790761186593.post-2210420437160146412013-05-22T09:11:00.000-07:002013-05-22T09:11:37.697-07:00Android Studio desktop entryI've been using IntelliJ for my Android development from the beginning. The new from #io13 that they were switching to an IntelliJ-based IDE was awesome. Of course, I had to download it and try it out.<br />
<br />
First thing to note is that although the Ultimate edition of IntelliJ is supposed to have the same support; the two are not exactly the same. Creating a new project in Android Studio has a different wizard (at least today).<br />
<br />
I installed Android Studio in /usr/local/android-studio. Upon launching Android Studio, I decided to try to do the "Configure | Create desktop entry".<br />
<br />
This unfortunately caused an exception:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">[ 10724] WARN - tions.CreateDesktopEntryAction - Unable to locate suitable startup script in '/usr/local/android-studio/bin'. </span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">java.lang.RuntimeException: Unable to locate suitable startup script in '/usr/local/android-studio/bin'.</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.ide.actions.CreateDesktopEntryAction.prepare(CreateDesktopEntryAction.java:148)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.ide.actions.CreateDesktopEntryAction.createDesktopEntry(CreateDesktopEntryAction.java:99)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.ide.actions.CreateDesktopEntryAction$1.run(CreateDesktopEntryAction.java:82)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.progress.impl.ProgressManagerImpl$TaskRunnable.run(ProgressManagerImpl.java:493)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.progress.impl.ProgressManagerImpl$2.run(ProgressManagerImpl.java:185)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:226)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcess(ProgressManagerImpl.java:175)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.progress.impl.ProgressManagerImpl$8.run(ProgressManagerImpl.java:400)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:458)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at java.util.concurrent.FutureTask.run(FutureTask.java:262)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at java.lang.Thread.run(Thread.java:722)</span><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span>at com.intellij.openapi.application.impl.ApplicationImpl$1$1.run(ApplicationImpl.java:154)</span></blockquote>
<div>
<br /></div>
<div>
The solution is just to create the desktop entry manually. Create the file <span style="font-family: Courier New, Courier, monospace;">~/.local/share/applications/android-studio.desktop</span>:</div>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">[Desktop Entry]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Version=1.0</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Comment=Develop Android with pleasure!</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Terminal=false</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Name=Android Studio</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Exec="/usr/local/android-studio/bin/studio.sh" %f</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Type=Application</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Icon=/usr/local/android-studio/bin/idea.png</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Categories=Development;IDE;</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">StartupNotify=true</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">StartupWMClass=jetbrains-idea</span><br />
<div>
<br /></div>
</blockquote>
</div>
<div>
<br /></div>
<div>
That's it. Depending on your OS version and window manager, you may need to restart X and/or log out.</div>
<div>
<br /></div>
Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com2tag:blogger.com,1999:blog-8434264790761186593.post-56035789811419164662013-05-09T00:01:00.001-07:002013-05-09T00:01:49.731-07:00Upgrading the Galaxy Note to Jelly BeanI received an SMS from AT&T today telling me that I could upgrade to JB using KIES. Enough acronyms for you?<br />
<br />
Rebooting into Windows so that I could launch Kies....<br />
Starting Kies, it detected that it was out of date and updated.<br />
Afterwards, plugging in the phone, it detected the firmware was out of date and tried to update.<br />
That's where things got redundant. I got in an infinite loop that kept stopping at:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmD1V11NlPyzwdGpey8gRIyAFgjBOayf15LpCCO8P0dQlOefPuFKHE3VJ6Q6mx69z4ILKIjXM593HPcr1HVJvK0gaGOML6ZsVmefaIHBiPHtT7ZLNrLcj8tlty5apg3vs80fsQt9RxY4VL/s1600/kies1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmD1V11NlPyzwdGpey8gRIyAFgjBOayf15LpCCO8P0dQlOefPuFKHE3VJ6Q6mx69z4ILKIjXM593HPcr1HVJvK0gaGOML6ZsVmefaIHBiPHtT7ZLNrLcj8tlty5apg3vs80fsQt9RxY4VL/s1600/kies1.png" /></a></div>
<br />
Now, don't get me wrong. My first thought was maybe I was down to 100MB internal storage <b><i>again</i></b>. I do tend to install a couple hundred apps.<br />
<br />
But, now according to the file manager:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGwUp2m-WGFgNMe3icyq79vX8JPipj3PLQgqf59gZmpBCIx5_eViFr63XsBUXhSbOfFdo4rNydXUTGw_QVJvV-b02gwIHK-x9c8OYxacNasKrnuz5MOjY7ptIXrOE-fkeQymdMK5xqrLFF/s1600/kies2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGwUp2m-WGFgNMe3icyq79vX8JPipj3PLQgqf59gZmpBCIx5_eViFr63XsBUXhSbOfFdo4rNydXUTGw_QVJvV-b02gwIHK-x9c8OYxacNasKrnuz5MOjY7ptIXrOE-fkeQymdMK5xqrLFF/s320/kies2.png" width="320" /></a></div>
<br />
So what's going on?<br />
<br />
After a few attempts, I went to Settings | Storage | Unmount SD Card<br />
<br />
After that Kies was able to upgrade the device.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-42248668950554001822013-03-24T03:13:00.000-07:002013-03-24T03:13:10.691-07:00ia32-libsAndroid is full of 32-bit tools and <a href="http://source.android.com/source/initializing.html" target="_blank">dependencies</a>.<br />
Running on x64 can be problematic unless you install ia32-libs.<br />
Unfortunately, Ubuntu has been having issues installing it lately.<br />
<br />
After 2 days, I finally found the solution <a href="https://bugs.launchpad.net/ubuntu/+source/ia32-libs/+bug/1016294/comments/27" target="_blank">here</a>:<br />
<br />
<blockquote class="tr_bq">
<pre style="color: black; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 1.3em; margin: 0px; max-height: 30em; overflow: auto; padding: 0px; text-align: start; text-indent: 0px; text-transform: none; word-spacing: 0px; word-wrap: normal;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: small;">sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install ia32-libs</span></span></pre>
</blockquote>
<br />
After that, everything installs fine. Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-83188328974422696612012-05-13T09:12:00.001-07:002012-05-13T09:13:13.597-07:00LMDE upgrade broke meWhile not strictly an Android issue, I figured I would post this here since it it related to my <a href="http://malsandroid.blogspot.com/2012/03/my-new-dev-box.html" target="_blank">previously mentioned</a> build box.<br />
<br />
Every time LMDE upgrades, it breaks my packages. At the very least, it breaks the nvidia driver (I should probably switch to source-based) but this last time, it auto uninstalled almost everything NVidia/Gnome/X11/Mate/Cinnamon/etc.<br />
<br />
You might be asking, "Why didn't you read the release notes that said to not upgrade yet?"<br />
<br />
Well, to be honest, I was used to the simplicity of the daily non-breaking Ubuntu updates. This new Debian tri-weekly breaking <i>rolling update</i> is a new beast to get used to. I put rolling update in italic because I don't understand how updating more packages less often is 'rolling'.<br />
<br />
Anyways, I spent the last 3 days trying to fix my box. It would boot fine - into a command line... but I really prefer to use Firefox/Chrome/Opera over links to do my web searching.<br />
<br />
I am sure these instructions are not the correct way to do things. You might even say it could be a bad idea to get into someones head. But since that was the only thing I tried that allowed me to start booting into X again, here we go.<br />
<br />
<b>STEP 1:</b><br />
First off, I determined something I thought should be installed. I don't know what the process in my head is for that, other than just selecting some random names I thought out to be there. For example '<span style="font-family: "Courier New",Courier,monospace;">gdm</span>'.<br />
<br />
<b>STEP 2:</b><br />
Secondly, I need to find out the correct name for it. IE: it's 'gdm3' not 'gdm'. For this, I did:<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">apt search gdm</span></div>
</blockquote>
and found the one that looked right (in this case 'gdm3').<br />
<br />
<b>STEP 3:</b><br />
Then, I needed to know whether it was actually installed yet or not -- and at which revision. For that I did: <br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">apt-cache policy gdm3</span></div>
</blockquote>
<br />
This showed that it was not currently installed! Well that doesn't sound right.<br />
<br />
<b>STEP 4:</b><br />
If step 3 showed the correct (updated) candidate:<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">apt install gdm3</span></div>
</blockquote>
If it fails to install, it might list some unmet dependency. If so, I start over at <b>STEP 3</b> (or <b>STEP 2</b> if that doesn't work) using that dependency as the new name to test.<br />
<br />
<b>STEP 5:</b><br />
If <b>STEP 3</b> showed the wrong (or no) candidate, I looked at the numbers [priority] at the beginning of each URL. It might show something like '500' for the one you want to install but '*** 700' for the one you have installed or it wants installed. Look at the URL for the one with the higher unwanted priority.<br />
<br />
<b>STEP 6:</b><br />
edit <span style="font-family: "Courier New",Courier,monospace;">/etc/apt/sources.list</span> and comment out the URL from STEP 5<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">apt update</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">apt dist-upgrade</span></div>
</blockquote>
Go to <b>STEP 3</b>.<br />
<br />
<br />
Like I said, these are probably not a good template to follow; however, next time instead of wasting 3 days trying to fix an upgrade I'll start here.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com2tag:blogger.com,1999:blog-8434264790761186593.post-48189887007254099852012-04-14T11:20:00.001-07:002012-04-14T11:20:25.251-07:00Unknown Host ExceptionI spent an hour trying to figure out why my little 1-page test app was throwing an UnknownHostException but the browser was working. To make matters worse, there was a red herring in that I could not ping from adb shell.<br />
<br />
Turns out it was a stupid ommission. If you are having this problem, don't forget to add this to your AndroidManifest:<br />
<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;"><uses-permission android:name="android.permission.INTERNET"/></span></div>
</blockquote>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-40988740527679445972012-03-20T15:50:00.000-07:002012-03-20T15:50:07.149-07:00Modify the emulator system.imgAs a followup to <a href="http://malsandroid.blogspot.com/2011/07/altering-systemimg-userdataimg-and.html" target="_blank">my earlier post</a>, I thought I would show how to modify the system.img the emulator is using.<br />
<br />
This assumes that you are building Android and want to use some of the generated APKs inside the stock emulator. That isn't the only scenario, but it's the one I am covering here.<br />
<br />
First, we need to determine where the images are being loaded from. In this case my AVD is called "<span style="font-family: "Courier New",Courier,monospace;">ics</span>".<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> grep sysdir ~/.android/avd/ics.avd/config.ini </span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">image.sysdir.2=system-images/android-14/armeabi-v7a/</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">image.sysdir.1=add-ons/addon-google_apis-google_inc_-14/images/armeabi-v7a/</span></span></blockquote>
<br />
Let's grab a local copy of those files <br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> cp $ANDROID_HOME/add-ons/addon-google_apis-google_inc_-14/images/armeabi-v7a/* .</span></span></blockquote>
<br />
This time around, we are interested in the <span style="font-family: "Courier New",Courier,monospace;">system.img</span>. Let's unpack it. <br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> mkdir unpacked</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> cd unpacked/</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system/unpacked$</b> unyaffs ../system.img </span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">end of image</span></span></blockquote>
<br />
Replace a couple apps <br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system/unpacked$</b> cd app</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system/unpacked/app$</b> cp ~/work/ics/out/target/product/SomeProduct/system/app/Contacts.apk .</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system/unpacked/app$</b> cp ~/work/ics/out/target/product/SomeProduct/system/app/ContactsProvider.apk .</span></span></blockquote>
<br />
Repack the system.img <br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system/unpacked/app$ </b>cd ../..</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$ </b>rm system.img</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$ </b>~/work/ics/out/host/linux-x86/bin/mkyaffs2image unpacked system.img</span></span></blockquote>
<br />
Point our AVD to our new images <br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> nano ~/.android/avd/ics.avd/config.ini</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">image.sysdir.2=system-images/android-14/armeabi-v7a/</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">image.sysdir.1=/home/malachi/work/redo_system/</span></span></blockquote>
<br />
The old userdata may not be compatible with your new apps. Make sure to use <i>-wipe-data</i>: <br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><b>malachi@onyx:~/work/redo_system$</b> emulator -avd ics -show-kernel -scale 0.70 -memory 1024 -logcat 'dalvikvm:S,StrictMode:S,*:D' -partition-size 1024 -wipe-data</span></span></blockquote>
<br />You are now running a slightly modified emulator...Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-55458752928916364272012-03-15T07:51:00.001-07:002012-03-24T12:57:24.703-07:00My New Dev BoxI'm hard on my machines. I do things like leave them number crunching at 100% cpu utilization for a week while I am out of the country. It should be no surprise that they tend to overheat, have power supplies or hard drives go out, et cetera.<br />
<br />
This time around, I have decided to take my time and try to head that off. I've been collecting parts one at a time and I'm honestly a little nervous about my first foray into watercooling -- but water + SSD should help with my core failures.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidOkVeleFoj3ZiraxU6Tei4quWWE8S6o8h7-_s3gpDpUMLpoLzOO4PGvXUuxbZ9J-oNInnfub_3ezI_uQ5DWAhrhr4I1y6SpVjZNZAena_x7yeO_TmcdfwUC_HN2FzNF4UYZbwAfUmZy7z/s1600/2012-03-15_06-33-21_132.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidOkVeleFoj3ZiraxU6Tei4quWWE8S6o8h7-_s3gpDpUMLpoLzOO4PGvXUuxbZ9J-oNInnfub_3ezI_uQ5DWAhrhr4I1y6SpVjZNZAena_x7yeO_TmcdfwUC_HN2FzNF4UYZbwAfUmZy7z/s320/2012-03-15_06-33-21_132.jpg" width="320" /></a></div>
<br />
Eventually I'll add things like triple monitors at 2560x1600 each -- but for now, it's a little light on the specs:<br />
<ul>
<li><b>Case:</b> <a href="http://www.thermaltakeusa.com/Product.aspx?C=1121&ID=2054" target="_blank">Thermaltake Level 10 GT LCS</a></li>
<li><b>Power Supply: </b><a href="http://thermaltakeusa.com/Product.aspx?S=1349&ID=2043" target="_blank">Thermaltake TPG-1200M</a></li>
<li><b>Memory:</b> <a href="http://www.corsair.com/memory-by-product-family/vengeance/vengeance-low-profile-16gb-dual-channel-ddr3-memory-kit-cml16gx3m4a1600c9.html" target="_blank">Corsair CML16GX3M4A1600C9</a></li>
<li><b>Motherboard: </b><a href="http://www.asus.com/Motherboards/AMD_AM3Plus/SABERTOOTH_990FX/" target="_blank">Asus 990FX Sabertooth</a></li>
<li><b>CPU:</b> <a href="http://products.amd.com/pages/DesktopCPUDetail.aspx?id=770" target="_blank">AMD FX-8150P</a></li>
<li><b>Video:</b> 2x <a href="http://www.evga.com/products/moreInfo.asp?pn=03G-P3-1591-AR&family=GeForce%20500%20Series%20Family&sw=" target="_blank">EVGA GeForce GTX 580 FTW Hydro Copper 2 3072 MB</a></li>
<li><b>BD:</b> <a href="http://www.pioneerelectronics.com/PUSA/Professional/Computer-Drives/BDR-206MBK" target="_blank">BDR-206MBK</a></li>
<li><b>Windows Drive:</b> <a href="http://www.crucial.com/store/partspecs.aspx?imodule=CT512M4SSD2CCA" target="_blank">Crucial M4 2.5" 512GB SATA III SSD</a></li>
<li><b>Linux Drive:</b> <a href="http://www.crucial.com/store/partspecs.aspx?imodule=CT512M4SSD2CCA" target="_blank">Crucial M4 2.5" 512GB SATA III SSD</a></li>
<li><b>WiFi:</b> <a href="http://homestore.cisco.com/en-us/adapters/linksys-WMP600N_stcVVproductId70015808VVcatId543809VVviewprod.htm?sourceid=SEM_A1_US_G_LOW-LINKSYS-WMP600N_ADAPTER-LINKSYS-PRODUCT_linksys-wmp600n_broad&gclid=CMjgjOHP4a4CFUgaQgodUjSDYg" target="_blank">Linksys WMP600N Wireless Dual-Band a/b/g/n </a></li>
<li><i>Accessories: </i></li>
<ul>
<li><a href="http://buy.logitech.com/store/logib2c/en_US/pd/ThemeID.23905600/productID.147364300/categoryId.37256600" target="_blank">Logitech Wireless Keyboard K350</a></li>
<li><a href="http://buy.logitech.com/store/logib2c/en_US/pd/ThemeID.23905600/productID.217924300/categoryId.37256100" target="_blank">Logitech Wireless Trackball M570</a></li>
<li><a href="http://www.logitech.com/en-us/gaming/headsets/devices/7248" target="_blank">Logitech Wireless Gaming Headset G930</a></li>
</ul>
<li><i>OS:</i></li>
<ul>
<li><a href="http://www.microsoft.com/windows/buy/windows-7-ultimate.aspx" target="_blank">Windows 7 Pro 64-bit</a> [some MMOs]</li>
<li><a href="http://www.linuxmint.com/download_lmde.php" target="_blank">Linux Mint 12 LMDE</a> (Debian Edition) [primary OS]</li>
</ul>
<li><i>I'll also be reusing my old <a href="http://www.samsung.com/us/support/owners/product/T240HD" target="_blank">Samsung SyncMaster T240HD</a> for now.</i></li>
</ul>
<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuO1sshbDnx-CzSuY842zxLEQ40fb9HtR8-cKN59t0S4QNb1cSzh6Kadfi4jMCnnecW-oOFELsc6Y39w65cZkRT5kZTl-qalCHAr2Ma8tuW2-3tYEFg98ZyYCidBO164elcTq5FHitOVtV/s1600/2012-03-10_11-44-33_67.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuO1sshbDnx-CzSuY842zxLEQ40fb9HtR8-cKN59t0S4QNb1cSzh6Kadfi4jMCnnecW-oOFELsc6Y39w65cZkRT5kZTl-qalCHAr2Ma8tuW2-3tYEFg98ZyYCidBO164elcTq5FHitOVtV/s320/2012-03-10_11-44-33_67.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg66xeFEf3h5TXSdgbBg74Kc4plmMhrpUqxGJb4WsGEkq83zFXmIBnPcOwvVOkaR2DHpmhqG_BDTbbK8RNXThiDQ9dOBngLIZ84FZh-LPUsTZPlyM9rFKO7_5Z02DL9XeNQmTYNDNbaM-bW/s1600/2012-03-10_11-48-19_660.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg66xeFEf3h5TXSdgbBg74Kc4plmMhrpUqxGJb4WsGEkq83zFXmIBnPcOwvVOkaR2DHpmhqG_BDTbbK8RNXThiDQ9dOBngLIZ84FZh-LPUsTZPlyM9rFKO7_5Z02DL9XeNQmTYNDNbaM-bW/s320/2012-03-10_11-48-19_660.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYru88RJ1IJdyHWwxAeWARHcjuJcdEDLYv9a4fuT88n6XX-wSU0Zlbhtq8RgGBdgFNhrcYquscX56Rr3cmY2tVYgO_fc9qOOELHJDG1YJBQOxL2bO1gGaHUz9qlqUI2KdOzHJMM5Ddi9PF/s1600/2012-03-11_12-51-22_122.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYru88RJ1IJdyHWwxAeWARHcjuJcdEDLYv9a4fuT88n6XX-wSU0Zlbhtq8RgGBdgFNhrcYquscX56Rr3cmY2tVYgO_fc9qOOELHJDG1YJBQOxL2bO1gGaHUz9qlqUI2KdOzHJMM5Ddi9PF/s320/2012-03-11_12-51-22_122.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
<br />
<br />
Before we go on, I realize you may be asking a few questions.<br />
<br />
<i><b>Q: Why are you installing Windows too?</b></i><br />
<b>A:</b> Unfortunately, some games I like to play are not available for Linux<br />
<br />
<i><b>Q: Why do dual-sli on a quad-sli board?</b></i><br />
<b>A:</b> I was planning on buying the watercooled GTX 590; but EVGA pulled them before I could. I'd rather try dual watercooled than quad air cooled.<br />
<br />
<i><b>Q: Why Mint instead of Ubuntu?</b></i><br />
<b>A:</b> Because Unity pisses me off. If I wanted a Mac-like interface, I would have bought one.<br />
<br />
<i><b>Q: Why Windows 7 instead of Windows 8?</b></i><br />
<b>A:</b> Because that tablet UI is disgusting. If I wanted a Mac-like interface, I would have bought one.<br />
<br />
<i><b>Q: Why buy 16GB ram when the board supports 32?</b></i><br />
<b>A:</b> Because the QVL didn't list any 32GB option. I decided to go with something officially supported.<br />
<br />
<i><b>Q: Why is the Linksys not in the pre-build image?</b></i><br />
<b>A:</b> Half way through the build I realized that everything in my house is wireless and nothing was wired. I ran to Fry's and picked it up.<br />
<br />
<i><b>Q: Why are the pictures so crappy?</b></i><br />
<b>A:</b> Unfortunately, it appears I do not have very good lighting in my house. This was on the dining room table, with chandelier above, stand lamp next to, flash on, window curtains open and all neighboring room lights on. It also made it near impossible to work on it after 5ish.<br />
<br />
<br />
Ok, onto the build...<br />
<br />
<b>Case:</b> <a href="http://www.thermaltakeusa.com/Product.aspx?C=1121&ID=2054" target="_blank">Thermaltake Level 10 GT LCS</a><br />
The case is really nice. It has these ports so that wiring can easily be ran behind the motherboard instead of over. Unfortunately for me, I rarely have cables long enough to justify it.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY319567j-_TfvkvwG68wcqLPj964OummyWGV8ZE8jaVYZ-35WpmJ34lGGZ2wcPQqWTbuPonh1XDs5H_tvYrHYzqKPJCIt9RvIkNZYMJD7HZkWUR0R6CI86wyeIFhm3Ax1U-HAqrrIjiuI/s1600/2012-03-10_12-01-15_507.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY319567j-_TfvkvwG68wcqLPj964OummyWGV8ZE8jaVYZ-35WpmJ34lGGZ2wcPQqWTbuPonh1XDs5H_tvYrHYzqKPJCIt9RvIkNZYMJD7HZkWUR0R6CI86wyeIFhm3Ax1U-HAqrrIjiuI/s320/2012-03-10_12-01-15_507.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2IyeH8UgM_KEHS-M3yEZoqXIGUYraWX67mdgiuqPcY9Zb40nKHAQx5Ti_nRqH2CsOV641vnI2hknJd48CUBxrnQQ1t2cI2NND0zMEPiovaReuAYxHqwKXU-iHOmGfzIwh-MN5-Gt4fctv/s1600/2012-03-10_12-01-21_718.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2IyeH8UgM_KEHS-M3yEZoqXIGUYraWX67mdgiuqPcY9Zb40nKHAQx5Ti_nRqH2CsOV641vnI2hknJd48CUBxrnQQ1t2cI2NND0zMEPiovaReuAYxHqwKXU-iHOmGfzIwh-MN5-Gt4fctv/s320/2012-03-10_12-01-21_718.jpg" width="320" /></a>
</td></tr>
</tbody></table>
The case comes a few items -- mostly for the water cooling. The open case panel in the picture comes off easily, and in fact was off for the entire build. The back panel also comes off, though that is more of a traditional slide under-edge type (which is not easy to get back on when you are tired).<br />
<br />
<br />
<br />
<b>Motherboard: </b><a href="http://www.asus.com/Motherboards/AMD_AM3Plus/SABERTOOTH_990FX/" target="_blank">Asus 990FX Sabertooth</a><br />
The motherboard is a very nice looking design. I like how the heat pipes look a bit aggressive. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTSRHWiKUa_OrfCupgyr6me3GJlfT6sIESoPmG3syyEleF6AhElfc6yss9I1I8VERKDRN67ePyoEV9DTlh4pZG9xV2u3pYG4sOW23Gye4a2chedDsafergjlpW2RJRX_Jf8CWhh5-RaZrV/s1600/2012-03-10_12-34-16_563.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTSRHWiKUa_OrfCupgyr6me3GJlfT6sIESoPmG3syyEleF6AhElfc6yss9I1I8VERKDRN67ePyoEV9DTlh4pZG9xV2u3pYG4sOW23Gye4a2chedDsafergjlpW2RJRX_Jf8CWhh5-RaZrV/s320/2012-03-10_12-34-16_563.jpg" width="320" /></a></div>
<br />
<br />
<br />
<b>CPU:</b> <a href="http://products.amd.com/pages/DesktopCPUDetail.aspx?id=770" target="_blank">AMD FX-8150P</a><br />
The CPU came in a nice tin - but most of the space is for the fan which we aren't going to use for this build. According to the manual, you void your warranty if you don't use their included fan -- but I'm going the watercooling route, so...<br />
<br />
<br />
<b>Installing the CPU into the Motherboard</b> <br />
<br />
CPU installation was a breeze. For some reason it took me awhile to find the arrow on the motherboard, but as you can see in this picture, it is clearly marked. I'll blame the bad lighting ;)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ_dg0Sc0wr-SNr0BmBZ4sZVdlc3UZK_3imhF_Is-lx7Pwmq6i9UVUR9rmFsh2ESymxPhyiqpw7WY54hTDt5MA7vZVKKME-V8OzY9YFLZE2Cfwod7jGifTDkDd_DunYHTLexendnjsoTS9/s1600/2012-03-10_13-00-20_888.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ_dg0Sc0wr-SNr0BmBZ4sZVdlc3UZK_3imhF_Is-lx7Pwmq6i9UVUR9rmFsh2ESymxPhyiqpw7WY54hTDt5MA7vZVKKME-V8OzY9YFLZE2Cfwod7jGifTDkDd_DunYHTLexendnjsoTS9/s320/2012-03-10_13-00-20_888.jpg" width="320" /></a></div>
<br />
<br />
<br />
<br />
<b>Installing the back plate</b> <br />
<br />
<br />
Installing the back plate was a bit tricky. Three of the edges were easy to get to, but the forth one required some finger contortions. Popping it in generally caused the others to come out. I even tried using tape to hold the others in place while I finagled the last one in. Eventually I got it without the tape, but it probably took me a good 15 minutes to snap it into place.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF0lEpzfKCwZnKbVP_Xc4dEmbHcHpxdRKEVqyiFdX-UAB7nMf1HpRrBPpXPmA5HOan-o6gb2JNX8UWh_NZC4EpbGpN_QrtcfgACBYqD-eSkWW8OHp5c61yqVQ7u70FNpHwIQFl1y9J6F8j/s1600/2012-03-10_13-10-10_807.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF0lEpzfKCwZnKbVP_Xc4dEmbHcHpxdRKEVqyiFdX-UAB7nMf1HpRrBPpXPmA5HOan-o6gb2JNX8UWh_NZC4EpbGpN_QrtcfgACBYqD-eSkWW8OHp5c61yqVQ7u70FNpHwIQFl1y9J6F8j/s320/2012-03-10_13-10-10_807.jpg" width="320" /></a></div>
<br />
<b>CPU Waterblock</b><br />
<br />
One of the reviews I read had warned to attach the hoses to the cpu waterblock before trying to put it on the CPU. That was great advise, because it took a LOT of pressure to get it on. To cut the correct length of tubing, I sat the waterblock in place and moved the tubing around until it looked like it would work without kinking. If I ever upgrade the watercooling, I think I might go for something that allows a smaller turn radius. You also need to screw the right braces onto the block. The case comes with 3 different sets. For AMD, they all use the same one, so it was easy enough to pick out. The black covers were a bit difficult to get off, but a small pair of needle nose pliers worked pretty well.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilF1vuBdEYv5xTe0WPZ5JEXphsRNWpxrzTiG3xYEbdbG0ZPurhYxwEKRr0T1OIXH9Rcyg69jhDS-FIhBekWLr4XHZW-xham8FLuh7kY4e6lrGYiYXPTo2nSP9abnMEGFu0WD3QaX9tJDb1/s1600/2012-03-10_13-58-41_298.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilF1vuBdEYv5xTe0WPZ5JEXphsRNWpxrzTiG3xYEbdbG0ZPurhYxwEKRr0T1OIXH9Rcyg69jhDS-FIhBekWLr4XHZW-xham8FLuh7kY4e6lrGYiYXPTo2nSP9abnMEGFu0WD3QaX9tJDb1/s320/2012-03-10_13-58-41_298.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguRyu86nK9bWTXiH5JDH3GL5SRWqVKYJES6dgw9kZprn8iBZoZbWF9tVMACK9y6Agqs9EP8p3oAfSIASZNn30-C242hwCZuyp7_4N8JGAZJvIvtj2hykzckodepI3Dbn5R7CVw7Zy2LqDB/s1600/2012-03-10_14-13-25_794.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguRyu86nK9bWTXiH5JDH3GL5SRWqVKYJES6dgw9kZprn8iBZoZbWF9tVMACK9y6Agqs9EP8p3oAfSIASZNn30-C242hwCZuyp7_4N8JGAZJvIvtj2hykzckodepI3Dbn5R7CVw7Zy2LqDB/s320/2012-03-10_14-13-25_794.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFXE9DO11OmoQ69lhZoyQ-G2QKYhKtOz4mHQOX5l2nkiIXt7uy7pQomVjRWp9vmIr42KjdxHP0-x2LFEBbgHVLiclYXhRrH8F56Ak0FvzEVzAO7I3K3TiB_Hel34XWk33VWTD3NvtMaFuI/s1600/2012-03-10_14-25-26_944.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFXE9DO11OmoQ69lhZoyQ-G2QKYhKtOz4mHQOX5l2nkiIXt7uy7pQomVjRWp9vmIr42KjdxHP0-x2LFEBbgHVLiclYXhRrH8F56Ak0FvzEVzAO7I3K3TiB_Hel34XWk33VWTD3NvtMaFuI/s320/2012-03-10_14-25-26_944.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
Adding the quick connect was trivial -- probably the easiest part of the entire water setup. I really hope these don't leak. Future upgrades might include me replacing all the connections with quick connects.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIrypzGL-khyz9U9MQXgIeYJtuswsMB4VL5T9icQf6SWJlIPfMNWHf18_GuzwOdzCc0Tydzt7cdC9I0odvwKzM9XJ-uHUFqYPPlKJEvvWaL8bdvciizTHCEycyMeO9pffay8ZJdjTJxVzU/s1600/2012-03-10_14-27-06_202.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIrypzGL-khyz9U9MQXgIeYJtuswsMB4VL5T9icQf6SWJlIPfMNWHf18_GuzwOdzCc0Tydzt7cdC9I0odvwKzM9XJ-uHUFqYPPlKJEvvWaL8bdvciizTHCEycyMeO9pffay8ZJdjTJxVzU/s320/2012-03-10_14-27-06_202.jpg" width="320" /></a></div>
<br />
<b>Memory:</b> <a href="http://www.corsair.com/memory-by-product-family/vengeance/vengeance-low-profile-16gb-dual-channel-ddr3-memory-kit-cml16gx3m4a1600c9.html" target="_blank">Corsair CML16GX3M4A1600C9</a><br />
I was really please with this memory. While adding it to the system, those radiator fans felt very nice. Others had warned about the CPU fan getting in the way, but that was not a problem for our water block. I was expecting both ends to snap in place, but it appears that only one side moves.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitHq1JOzdesq-N-LZUv7wXZbLGC94YM4Df8BW79-30SzRTdSWUL6FgYZu70G_Wo9SdswNqP3l_-u7rFlsp0cBUMonXuUdoRXHeFE9MLgNMy_ZwVsnuQVDrgcifMrVc21gp0HdPKuONbmfC/s1600/2012-03-10_14-31-13_522.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitHq1JOzdesq-N-LZUv7wXZbLGC94YM4Df8BW79-30SzRTdSWUL6FgYZu70G_Wo9SdswNqP3l_-u7rFlsp0cBUMonXuUdoRXHeFE9MLgNMy_ZwVsnuQVDrgcifMrVc21gp0HdPKuONbmfC/s320/2012-03-10_14-31-13_522.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnrhhjAs2_DdZB4f9b66KWAfilnHG3Zqq1XeY86MOM7ULh2qs3L10HK4b_t3GQDK-lUoZosLL4Wd1r7I7jNYIIzTsgeGmROoyyfSK1GRPPyyuLFGhI5V-TZ0EJQKnT-736t0WkFwAnLYB6/s1600/2012-03-10_14-36-30_6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnrhhjAs2_DdZB4f9b66KWAfilnHG3Zqq1XeY86MOM7ULh2qs3L10HK4b_t3GQDK-lUoZosLL4Wd1r7I7jNYIIzTsgeGmROoyyfSK1GRPPyyuLFGhI5V-TZ0EJQKnT-736t0WkFwAnLYB6/s320/2012-03-10_14-36-30_6.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioNhAkQ5jMydm464zVKC1yC6ipWCwpmOw8qDTelw4m-bND7S2pBa9ZNOh9K6ttrvKw2tEP-wQSgD81scAmHNe007y26KpFXRnJoJQxnSMDZGm1Mr6dfGwSahyphenhyphen8LgsKpNp2_J6zzimmTbMq/s1600/2012-03-10_14-36-36_774.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioNhAkQ5jMydm464zVKC1yC6ipWCwpmOw8qDTelw4m-bND7S2pBa9ZNOh9K6ttrvKw2tEP-wQSgD81scAmHNe007y26KpFXRnJoJQxnSMDZGm1Mr6dfGwSahyphenhyphen8LgsKpNp2_J6zzimmTbMq/s320/2012-03-10_14-36-36_774.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
<b>Thermal paste</b><br />
<br />
I've never had to install thermal paste before. There was always some sticker like thing provided to use instead. This time around I had to use the thermal paste. I have no clue why they provided it in a syringe type of container, because all it does is bulk up at the tip like gooey wet silly putty. I thought for a minute that maybe something was wrong with it, with the consistency. To be honest, I don't know. Since I am cooling with water, I'm hoping it is OK. It that is the consistency it is supposed to be, I think the industry should really reconsider the delivery mechanism. I tried spreading it over the entire CPU, but this was the best I was able to do. Maybe it spread out a little bit when the water block was clamped down. Here's hoping.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDP2urGEhrGkSSJFv3_mCVVcL_h61sAnhfWrVHyE554Sgt7jSCK8dkLCj7wCvDg-5eVb0BH4NrUJoIi6hFKqMsTFXM7COPXNJauPMxqSvAGP3w91ifbtBkyq44-GBp9ewcMu85gnJ8CkHE/s1600/2012-03-10_14-38-07_792.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDP2urGEhrGkSSJFv3_mCVVcL_h61sAnhfWrVHyE554Sgt7jSCK8dkLCj7wCvDg-5eVb0BH4NrUJoIi6hFKqMsTFXM7COPXNJauPMxqSvAGP3w91ifbtBkyq44-GBp9ewcMu85gnJ8CkHE/s320/2012-03-10_14-38-07_792.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1-zslpL-cI0ethsN-FvrJ4TKPNveIfr9ews4heST0xiyVDJWui-hn4_-5oSvlknAAgKRoB5qGX3Gjg11i59iL6AkK1JgXjgQazDqDYdblCeMrdYfFSuuDKECJPr8Dp7NrGiGRj6aVpDvP/s1600/2012-03-10_14-40-14_799.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1-zslpL-cI0ethsN-FvrJ4TKPNveIfr9ews4heST0xiyVDJWui-hn4_-5oSvlknAAgKRoB5qGX3Gjg11i59iL6AkK1JgXjgQazDqDYdblCeMrdYfFSuuDKECJPr8Dp7NrGiGRj6aVpDvP/s320/2012-03-10_14-40-14_799.jpg" width="180" /></a>
</td></tr>
</tbody></table>
<br />
<br />
<b>Install the water cooling block</b><br />
<br />
Installing the block wasn't so bad. It was difficult to see whether the braces were on correctly before clamping down. Installing the quick connect was very nice.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizrIn7up6hlSjWZEE-7KmdJpl3e06aNX4rB8oHlbij6qOMVZ8SFHGLF5i2eEA8UYU9jPgstDOEpwE5sls3mdi-A47LwSBBu3qQmOdwXhArFI81u-nPAZxg4gz7Lmy_JIDlREYKsaj2cvjV/s1600/2012-03-10_14-42-21_372.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizrIn7up6hlSjWZEE-7KmdJpl3e06aNX4rB8oHlbij6qOMVZ8SFHGLF5i2eEA8UYU9jPgstDOEpwE5sls3mdi-A47LwSBBu3qQmOdwXhArFI81u-nPAZxg4gz7Lmy_JIDlREYKsaj2cvjV/s320/2012-03-10_14-42-21_372.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZs1aJiZAqXIRw2656VtIE1sLIwaCrr_vNsiJOBudHFQKlomF95iNEmhzjH8JzBMv8IdyUvhp58gVL1FrCB2OPfgztNtyl3lHDtl9ZxrxZMaqQGen23jSkQwN7OPzrSi_nD7zxiImTdArG/s1600/2012-03-10_14-47-37_604.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZs1aJiZAqXIRw2656VtIE1sLIwaCrr_vNsiJOBudHFQKlomF95iNEmhzjH8JzBMv8IdyUvhp58gVL1FrCB2OPfgztNtyl3lHDtl9ZxrxZMaqQGen23jSkQwN7OPzrSi_nD7zxiImTdArG/s320/2012-03-10_14-47-37_604.jpg" width="320" /></a>
</td></tr>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD131EqjR7jAfbKgMNFSt4ydj3mwhK_ZDD2B-xWWNqchtmMnugvdiv5mQu2ndRcQ6SGZUky6XQYwQGETDAULczde4ML_k1HgajueDUCSpAZ3_dUQGulVonwA70JSoc4bHkTZzUdDLyol48/s1600/2012-03-10_14-42-38_565.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD131EqjR7jAfbKgMNFSt4ydj3mwhK_ZDD2B-xWWNqchtmMnugvdiv5mQu2ndRcQ6SGZUky6XQYwQGETDAULczde4ML_k1HgajueDUCSpAZ3_dUQGulVonwA70JSoc4bHkTZzUdDLyol48/s320/2012-03-10_14-42-38_565.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUqjejEmfd1KBtvbSuEH41kcsFBk2LtKPF2UKwRbveGC2b15UtpT8mVs1okZjkfC_53R8kwX5BlFI3ZdDedTSOtoYt9XA9JhDGOrzaT4SLKcfJWuAJjrmE7Wlil62voKRokF71MW0O9jxM/s1600/2012-03-10_14-45-21_137.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUqjejEmfd1KBtvbSuEH41kcsFBk2LtKPF2UKwRbveGC2b15UtpT8mVs1okZjkfC_53R8kwX5BlFI3ZdDedTSOtoYt9XA9JhDGOrzaT4SLKcfJWuAJjrmE7Wlil62voKRokF71MW0O9jxM/s320/2012-03-10_14-45-21_137.jpg" width="180" /></a>
</td></tr>
</tbody></table>
In order to keep the tubing from hitting the fan on the side of the case, I put a twisty tie (it was holding the accessory box inside the case during shipping) to anchor it to the top of the case. The top (and bottom actually) of the case are netted, so putting something through is very easy.<br />
<br />
<b>Power Supply: </b><a href="http://thermaltakeusa.com/Product.aspx?S=1349&ID=2043" target="_blank">Thermaltake TPG-1200M</a><br />
I was actually impressed with the packaging of the power supply, In addition to a felt bag for the accessories and a felt (not plastic) bag for the power supply itself, it also came with a little velcro case for the modular cables. I was a little confused why a couple items were outside the bags, but overall it was a nice presentation.<br />
<br />
Installing it was easy with the exception that the provided rubber gaskets didn't fit anywhere correctly. I ended up using them for the top holes - but IMHO the gaskets should have connected to all the screw holes.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWNFgDaZlvaIThNdRNBLYfnVdVgyFnwBdJC8ArRLpaKdX73Vq7utzBzTCirTLsxom67zE5VjqVWNhCsVKFatwyKhyphenhyphenw0fNdt6zW_ar7yJq0rwWx0R_xsYrYtHoWPYGawDoaRHXq4xwEIBLt/s1600/2012-03-11_10-50-00_861.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWNFgDaZlvaIThNdRNBLYfnVdVgyFnwBdJC8ArRLpaKdX73Vq7utzBzTCirTLsxom67zE5VjqVWNhCsVKFatwyKhyphenhyphenw0fNdt6zW_ar7yJq0rwWx0R_xsYrYtHoWPYGawDoaRHXq4xwEIBLt/s320/2012-03-11_10-50-00_861.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYoz5QkMm3-7kKUiWXC2S9wLP-7Sd0oANmanvQnKBECoo2gpW7cp25sEErtYEQT9vxoylqhyWyrPjtrSMbpAK9ZpZqtvdCX2d66FF-wrG5aIzmQ6YLU4L8u225MURlG7dfYGpceWloeD7y/s1600/2012-03-11_11-09-47_626.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYoz5QkMm3-7kKUiWXC2S9wLP-7Sd0oANmanvQnKBECoo2gpW7cp25sEErtYEQT9vxoylqhyWyrPjtrSMbpAK9ZpZqtvdCX2d66FF-wrG5aIzmQ6YLU4L8u225MURlG7dfYGpceWloeD7y/s320/2012-03-11_11-09-47_626.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
I really like that the PSU sits in the bottom of the case; but I wish there was a little more clearance between it and the motherboard. It made it difficult to get some of the connects in since my hand was too hide for the space.<br />
<br />
<br />
<b>Windows Drive:</b> <a href="http://www.crucial.com/store/partspecs.aspx?imodule=CT512M4SSD2CCA" target="_blank">Crucial M4 2.5" 512GB SATA III SSD</a><br />
<b>Linux Drive:</b> <a href="http://www.crucial.com/store/partspecs.aspx?imodule=CT512M4SSD2CCA" target="_blank">Crucial M4 2.5" 512GB SATA III SSD</a><br />
These "drives" are small, lightweight, no moving parts and SATA III. What's not to love. To mount them, first turn the key to Unlock, push the button while pulling the drawer out. Screen the drive to the drawer. Push it in.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvgXSrmxgvEa4H9JgYlwaAPNRdbhqdPK9m6K-lPmXZOvQYMIn1DCqxvdZBZL0lxCMmrebOYHjA9SZCpEsqCmdrLWWflFF6oyGhV98k0P7sp6Sm_zSmtTZ1PfjNOYxpYRhTxUz-TYOJiFqj/s1600/2012-03-11_11-28-08_844.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvgXSrmxgvEa4H9JgYlwaAPNRdbhqdPK9m6K-lPmXZOvQYMIn1DCqxvdZBZL0lxCMmrebOYHjA9SZCpEsqCmdrLWWflFF6oyGhV98k0P7sp6Sm_zSmtTZ1PfjNOYxpYRhTxUz-TYOJiFqj/s320/2012-03-11_11-28-08_844.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFE2GDqzOAZb4oizcjgRVYMyNgKAzXRK03sdIjnvOtt5ECOkfeEcyuVe9JR8zoRU6ehI4Yk7YTTvSkqaDFImKr1scM7bgBZTWfjLvIbaxS4xCKdUVcNWqBAZGFEsxC5LLqgQXE4iI1X1S5/s1600/2012-03-11_11-29-35_165.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFE2GDqzOAZb4oizcjgRVYMyNgKAzXRK03sdIjnvOtt5ECOkfeEcyuVe9JR8zoRU6ehI4Yk7YTTvSkqaDFImKr1scM7bgBZTWfjLvIbaxS4xCKdUVcNWqBAZGFEsxC5LLqgQXE4iI1X1S5/s320/2012-03-11_11-29-35_165.jpg" width="320" /></a>
</td></tr>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBAfLpQ7YRc9GNb8Q_JpIgYsP8xtyR-muotBkM8AW4hGgW_Eq25I3EwMeKNYhnnnWTJCZLQWnUTeVfzngVjgjSwiH1wzpt_BSfPW2I72bfOwFFDgG_ey9FqxNDbjncWc6WXoCbaVjIkyCT/s1600/2012-03-11_11-33-38_55.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBAfLpQ7YRc9GNb8Q_JpIgYsP8xtyR-muotBkM8AW4hGgW_Eq25I3EwMeKNYhnnnWTJCZLQWnUTeVfzngVjgjSwiH1wzpt_BSfPW2I72bfOwFFDgG_ey9FqxNDbjncWc6WXoCbaVjIkyCT/s320/2012-03-11_11-33-38_55.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu8Zht_A1uAIyUfTYQgkB1erGZK9008Omai84HBYt7NwtOtsjxukTNKbmCtRGt8zjQJkC-QB6QJeUo89sQoUkwJDHf5V6y589Mj_NheVDSX1CRTO_SGMxtaMnFsH1Kjx52e60g6BRq7OjZ/s1600/2012-03-11_11-37-46_200.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu8Zht_A1uAIyUfTYQgkB1erGZK9008Omai84HBYt7NwtOtsjxukTNKbmCtRGt8zjQJkC-QB6QJeUo89sQoUkwJDHf5V6y589Mj_NheVDSX1CRTO_SGMxtaMnFsH1Kjx52e60g6BRq7OjZ/s320/2012-03-11_11-37-46_200.jpg" width="180" /></a>
</td></tr>
</tbody></table>
Note in the last picture the band of power cabling. It goes to a power connector hanging loose under the bottom drive. <br />
<br />
<b>Video:</b> 2x <a href="http://www.evga.com/products/moreInfo.asp?pn=03G-P3-1591-AR&family=GeForce%20500%20Series%20Family&sw=" target="_blank">EVGA GeForce GTX 580 FTW Hydro Copper 2 3072 MB</a><br />
The video cards are pretty. And heavy. The box contains barbs and rings for two different tubes. It also comes with the power cables and a couple adapters.<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj3nk6G1x-poCwK7hfN-zS5o_sb_zdXP0De1Ll6OhQgQ3t5eM6l6kjzL2b9X9_fb4OHTQb1Qo8FPl_Dn7UvZfYLgsN1sbB4yBOPij6Dkqmd3S18gWK4vJ_C3SwrKAU89F2E6MRGinNzCNL/s1600/2012-03-11_11-48-48_281.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj3nk6G1x-poCwK7hfN-zS5o_sb_zdXP0De1Ll6OhQgQ3t5eM6l6kjzL2b9X9_fb4OHTQb1Qo8FPl_Dn7UvZfYLgsN1sbB4yBOPij6Dkqmd3S18gWK4vJ_C3SwrKAU89F2E6MRGinNzCNL/s320/2012-03-11_11-48-48_281.jpg" width="320" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9TOL5Ou2IzH2a66boB3iTXyge4sgnH27Nc2AHGr_mSVgAzC8LceSmsinhJEHNP52xkI297oNzACsr311gl1e8MELvSfxTDFbQw3qxkSmJm6Ot6NsFwexIveCY8ksvS4zouXpGCRBOXiZ5/s1600/2012-03-11_11-48-55_490.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9TOL5Ou2IzH2a66boB3iTXyge4sgnH27Nc2AHGr_mSVgAzC8LceSmsinhJEHNP52xkI297oNzACsr311gl1e8MELvSfxTDFbQw3qxkSmJm6Ot6NsFwexIveCY8ksvS4zouXpGCRBOXiZ5/s320/2012-03-11_11-48-55_490.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
<br />
To determine which position to put the barbs, I sat the card in the case where it is going to go and again manhandled the tubing until I found a non-crinking way to tube it. That led me to putting the one closest to the CPU further away from the water source so there was more room for the water loop. For the second one, I decided it would be easier to do a straight tube between them than to try to curve it.<br />
<br />
<table border="0">
<tbody>
<tr><th>First Card</th><th>Second Card</th></tr>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYJxSoV7oDp0KeX7W3GAfwnzsQTBUnuMAJqRvYDd88FUKj9elxTg2zHhGFosTUJvtHtuqjrIjB46m-kzaVLyRYSbQ0_Wsb79I115hjHpTpuRtWMogJOp98NVj0IykNEjSQOQ8rhagwjo_7/s1600/2012-03-11_12-21-07_743.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYJxSoV7oDp0KeX7W3GAfwnzsQTBUnuMAJqRvYDd88FUKj9elxTg2zHhGFosTUJvtHtuqjrIjB46m-kzaVLyRYSbQ0_Wsb79I115hjHpTpuRtWMogJOp98NVj0IykNEjSQOQ8rhagwjo_7/s320/2012-03-11_12-21-07_743.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgegaaE1ox9VWLuZ9_2deEGoa7TVCmZ4rkSqtJdMgrHSvEizvEnc_SYzyljFm8Ede5QAC9OuYJm9GKQjfG50_sfbOn3cLWKadZExwgALfY6mPsMMm2G5OOqwde52uSJB6mxjZ2ZyV4Br9xk/s1600/2012-03-11_12-39-48_41.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgegaaE1ox9VWLuZ9_2deEGoa7TVCmZ4rkSqtJdMgrHSvEizvEnc_SYzyljFm8Ede5QAC9OuYJm9GKQjfG50_sfbOn3cLWKadZExwgALfY6mPsMMm2G5OOqwde52uSJB6mxjZ2ZyV4Br9xk/s320/2012-03-11_12-39-48_41.jpg" width="180" /></a>
</td></tr>
</tbody></table>
One odd thing was that the second card had an extra rubber washer on it. At first I took the cards apart again trying to figure out which one was messed up. When I realized that one had an extra rubber on it, it took me a minute to decide whether to remove it or not. In the end, I decided that it might be less likely to leak with it (I hope) so I kept it on. Assuming it doesn't cause a problem, I kinda wish I had the extra on all the other barbs. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcb1Hirq1S2kGFGkKrr7LmORwe7J38Wag06z88hd5zadpBk4QEPS7v0Ot4KxJRNkZkRTgPpgXuxFGHV64kc_7jax8zJ6A3dO0edcAcV_Dn93D0PdRF5EufmyALpwlH-zVNwZjs4wJ2Lomz/s1600/2012-03-11_12-39-53_213.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcb1Hirq1S2kGFGkKrr7LmORwe7J38Wag06z88hd5zadpBk4QEPS7v0Ot4KxJRNkZkRTgPpgXuxFGHV64kc_7jax8zJ6A3dO0edcAcV_Dn93D0PdRF5EufmyALpwlH-zVNwZjs4wJ2Lomz/s320/2012-03-11_12-39-53_213.jpg" width="180" /></a></div>
<br />
<br />
When installing the first card, it went in without a hitch. The second card was a bit more cramped as the sata connectors sit under it. Well, that and I had forgotten to take the plate off:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBF7-2bHj4eEE5zgMQV8ZK-9RG9jjRgSq6BZG3c6-apjyiLWqugVX_P9w20qbfz3GK7Vafc_Vzd8O32sDncRuboVvlDd85Dcg9wE7UpjrvipKb9k9kVhDO8G8WGXYHkXV1PGIDrnSEoXw-/s1600/2012-03-11_12-50-33_170.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBF7-2bHj4eEE5zgMQV8ZK-9RG9jjRgSq6BZG3c6-apjyiLWqugVX_P9w20qbfz3GK7Vafc_Vzd8O32sDncRuboVvlDd85Dcg9wE7UpjrvipKb9k9kVhDO8G8WGXYHkXV1PGIDrnSEoXw-/s320/2012-03-11_12-50-33_170.jpg" width="180" /></a></div>
Taking that off (10 minutes later) helped get the second card in without much additional hassle.<br />
<br />
<b>WiFi:</b> <a href="http://homestore.cisco.com/en-us/adapters/linksys-WMP600N_stcVVproductId70015808VVcatId543809VVviewprod.htm?sourceid=SEM_A1_US_G_LOW-LINKSYS-WMP600N_ADAPTER-LINKSYS-PRODUCT_linksys-wmp600n_broad&gclid=CMjgjOHP4a4CFUgaQgodUjSDYg" target="_blank">Linksys WMP600N Wireless Dual-Band a/b/g/n </a><br />
Earlier in the day, I remembered that everything in the house was wireless. I also remembered that the printer worked only with the wireless computers when in wireless mode and only with the wired computers when it wired mode. Why? I don't know - never took the time to figure it out. Probably a problem with the routing on the $34 wifi router (which I also decided I am going to replace). Long story short, I decided I wanted wifi. I didn't want a USB adapter because my cat likes to climb on things, so I opted for a PCI card. I was going to buy the PCIe card at Fry's instead, but then I saw the dual-band and decided that might be a better choice.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmGlposPkZEOYzg8QJtC-L1F7PUcBrxVF13VrzlNGGfmRy2rG-5iqXfpptT-gbq40c2PV3rGXfKzaNDpUd5Z8onLGkpco6xJQAND4zkRmeyWZbnNzq4Aw4FTLIJo-5VbHN3Zb5NKXXK7tL/s1600/2012-03-11_12-53-49_137.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmGlposPkZEOYzg8QJtC-L1F7PUcBrxVF13VrzlNGGfmRy2rG-5iqXfpptT-gbq40c2PV3rGXfKzaNDpUd5Z8onLGkpco6xJQAND4zkRmeyWZbnNzq4Aw4FTLIJo-5VbHN3Zb5NKXXK7tL/s320/2012-03-11_12-53-49_137.jpg" width="320" /></a></div>
<br />
<br />
<br />
<br />
So, there aren't many standard PCI slots anymore. Mine happened to be pretty close to touching the 2nd GTX 580. At first I was nervous about them being that close, then I thought 'hey, maybe it will get some minor cooling from the nearby waterblock'. Besides the component was on the other side.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy09hTmY90fNOQ9IiFjwrhNFEvqKf_qJRmPe-ipi-UFnJgw-LkFTvzLMn2tHDBAW09-MhmCJVTMEKEZc7hjK9Oq2eaERVFcuw0KdZvWYK96mshSarWNWZoLbqc2oirySPE467u0vZ9azkO/s1600/2012-03-11_12-59-09_891.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy09hTmY90fNOQ9IiFjwrhNFEvqKf_qJRmPe-ipi-UFnJgw-LkFTvzLMn2tHDBAW09-MhmCJVTMEKEZc7hjK9Oq2eaERVFcuw0KdZvWYK96mshSarWNWZoLbqc2oirySPE467u0vZ9azkO/s320/2012-03-11_12-59-09_891.jpg" width="320" /></a></div>
<br />
<b>Time to finish off the tubing</b><br />
<br />
I adding the SLI connector and the small tube between the cards.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjILMykQ6dFYds8s-8vFKXpiAsolZRHVKyeyP5ftGgiLIsYlFzGtZZkxWO04KLU-aYrw030G4Cu7IBt81_Heo8kttzu8HFVJsDkTzcNobQo1X-W-4snm-OqhIjKiY_9hIFjFnwA64bfy4g9/s1600/2012-03-11_13-05-44_428.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjILMykQ6dFYds8s-8vFKXpiAsolZRHVKyeyP5ftGgiLIsYlFzGtZZkxWO04KLU-aYrw030G4Cu7IBt81_Heo8kttzu8HFVJsDkTzcNobQo1X-W-4snm-OqhIjKiY_9hIFjFnwA64bfy4g9/s320/2012-03-11_13-05-44_428.jpg" width="180" /></a></div>
<br />
Connected the first card to the loop<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXX538XHywE28QZ0kbAWCyUIsBgPCMzHglyzeGg6VuOM01nYPoYTUHh0qtdeiUKdbIRpRI88UefWRuQ_69YgZApF6oO95_C0iqFz6Bud-LV6rmp0A0s29oHF3jbOPB3ANi4bAFgq3qjPzB/s1600/2012-03-11_14-31-08_470.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXX538XHywE28QZ0kbAWCyUIsBgPCMzHglyzeGg6VuOM01nYPoYTUHh0qtdeiUKdbIRpRI88UefWRuQ_69YgZApF6oO95_C0iqFz6Bud-LV6rmp0A0s29oHF3jbOPB3ANi4bAFgq3qjPzB/s320/2012-03-11_14-31-08_470.jpg" width="180" /></a></div>
<br />
And connected the second card back to the reservoir.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8OyIzMvB9d0wy_HbtIWmlQoTdnN9klXwrZUD2N9Xnl-OAna8mY8fvL7kLgHkyeM0C2jUFfH2WcCnLHFe2-1PDZkHVSsnU9Vz409RM-xEi8fEmhmIelWdL-Fxvd-nGvwL_dETRwGFvFpKb/s1600/2012-03-11_14-35-51_9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8OyIzMvB9d0wy_HbtIWmlQoTdnN9klXwrZUD2N9Xnl-OAna8mY8fvL7kLgHkyeM0C2jUFfH2WcCnLHFe2-1PDZkHVSsnU9Vz409RM-xEi8fEmhmIelWdL-Fxvd-nGvwL_dETRwGFvFpKb/s320/2012-03-11_14-35-51_9.jpg" width="180" /></a></div>
<br />
<b>Connect motherboard to PSU</b><br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfaxiHwxZgWkOT1sTPoXI0TIoFk6JsQIzcUECUK05CFOoIa9AkD92BYgY60NgaQ5c0tu20W0yMGT_J_9iANOipjF0UaIoBmvcpA2iDOnykZXS9s94jCxQ9md20bA0BDw-ph1983ou5DKU5/s1600/2012-03-11_14-55-19_460.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfaxiHwxZgWkOT1sTPoXI0TIoFk6JsQIzcUECUK05CFOoIa9AkD92BYgY60NgaQ5c0tu20W0yMGT_J_9iANOipjF0UaIoBmvcpA2iDOnykZXS9s94jCxQ9md20bA0BDw-ph1983ou5DKU5/s320/2012-03-11_14-55-19_460.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3fj7G9pjOsM-1NxaaWVM9TK41qSP7c0ax4-pL2Rt4jQMt-d1g5XMvWN0vmgPaVU-_jupWLX3CABCQw0OmF4veGgd2-H9YXp_0T3pJpUVxC0w29Os7VWJ1FNJUoySq3UQMi74quaay3_ZK/s1600/2012-03-11_14-55-25_21.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3fj7G9pjOsM-1NxaaWVM9TK41qSP7c0ax4-pL2Rt4jQMt-d1g5XMvWN0vmgPaVU-_jupWLX3CABCQw0OmF4veGgd2-H9YXp_0T3pJpUVxC0w29Os7VWJ1FNJUoySq3UQMi74quaay3_ZK/s320/2012-03-11_14-55-25_21.jpg" width="180" /></a>
</td></tr>
</tbody></table>
<br />
<b>And power connectors to the video cards</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7zv3QJi1qKwaCbvMlvVdBpeLLhXn8W65WtFKIUzh2abN_dR3ZbfPJ-dXubOiQbT8P4iIpbBRxWl5J7elZm81pd7M1dpmYiXnEDXls1FlX0xoDVYPzSdpcaml8P1WnhRB0mSAh8bmClkj/s1600/2012-03-11_14-55-36_961.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7zv3QJi1qKwaCbvMlvVdBpeLLhXn8W65WtFKIUzh2abN_dR3ZbfPJ-dXubOiQbT8P4iIpbBRxWl5J7elZm81pd7M1dpmYiXnEDXls1FlX0xoDVYPzSdpcaml8P1WnhRB0mSAh8bmClkj/s320/2012-03-11_14-55-36_961.jpg" width="320" /></a></div>
<br />
<br />
<br />
<br />
<br />
<b>The Diabolical USB 3.0 Header</b><br />
<br />
<br />
I had actually connected some more cabling and was almost done when I tried to plug in the USB 3.0 header for the top of the case. I probably should have seen the problem right away and shaved it -- but before I realized what was going on, one of the pins in the header was bent over. Unfortunately, it was the one in the corner away from the graphics card, so I was having a lot of trouble getting a good angle. I told myself I should take everything apart, but I tried one too many times and broke the pin off. Looks like the 2 USB 3.0 jacks on the top of the case will go un-utilized. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS1cY-4jIL1j4glzjeb5fihqtBjh0UN6GI_pR4EOjZR9FFggFjTCVoSHEbuXUhJiuICx6iBLVd08iAidUHBVhsvGMRrMQGIZ1b6Iy3ga0gY3K288t6iu7xqP-v_76g82pMGThsuRXoFVMW/s1600/2012-03-11_15-35-36_932.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="183" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS1cY-4jIL1j4glzjeb5fihqtBjh0UN6GI_pR4EOjZR9FFggFjTCVoSHEbuXUhJiuICx6iBLVd08iAidUHBVhsvGMRrMQGIZ1b6Iy3ga0gY3K288t6iu7xqP-v_76g82pMGThsuRXoFVMW/s320/2012-03-11_15-35-36_932.jpg" width="320" /></a></div>
<br />
<br />
<b>... insert time taken to plug in all the cabling ...</b><br />
<br />
Most of the cabling was easy enough to connect. As stated, the USB 3.0 header wasn't. The connections near the PSU were a little difficult. The power connector for the SATA bays hiding underneath the bottom tray took a moment to find...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx3VXbSQJjJyjveUPtKDGPwvbfi2AdnsTTsW-Afqs6DO6yfcA0PKEU8JYzLPhnXraKB1ZXLWMAKHosGCkOVxo0Me6EUl8bDo7V6Y90Aa3LUqMJCK1A271b6oSayr_VM4JrHol0ungOGHjl/s1600/2012-03-13_19-17-04_906.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx3VXbSQJjJyjveUPtKDGPwvbfi2AdnsTTsW-Afqs6DO6yfcA0PKEU8JYzLPhnXraKB1ZXLWMAKHosGCkOVxo0Me6EUl8bDo7V6Y90Aa3LUqMJCK1A271b6oSayr_VM4JrHol0ungOGHjl/s320/2012-03-13_19-17-04_906.jpg" width="180" /></a></div>
<br />
<br />
But the LED/Fan control didn't work. A couple fans were spinning, water was moving, but the door fan (when closed) did not spin and none of the LEDs came on, and the LED Fan Controller had no power. I get the impression I am missing a molex connector somewhere, but as of yet have not found it. One thing that I thought was kind of odd is that on the back of the case, there are 3 headers but only two cables... What's that about?<br />
<br />
<table border="0">
<tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3cm1l-z1lAk16h6x9gDIKM5dv11zPoiB8EEzAvam9U29V7ElmZVs8v2hgH6qyQetXtfSQVgaAnHGFSZTZEq5IVmanSR7B7sDQHGv3vg-atQ0iKnVDC47yqH7MIhTBvs0TtluAxs5QcXQU/s1600/2012-03-13_20-13-01_540.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3cm1l-z1lAk16h6x9gDIKM5dv11zPoiB8EEzAvam9U29V7ElmZVs8v2hgH6qyQetXtfSQVgaAnHGFSZTZEq5IVmanSR7B7sDQHGv3vg-atQ0iKnVDC47yqH7MIhTBvs0TtluAxs5QcXQU/s320/2012-03-13_20-13-01_540.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0LOksHvxBjRWiuPyheWvxxxpgUB8tpG8qLYM1K6AbHdV_HowFcerC_BkidMRyBxWRDpfnQELgBFkuNTE5MifMu1oOdlod2kMlMEK8xqYLxIWIrf8r_DJgAG70a0xYK_oaeOAVhWEwNHPc/s1600/2012-03-13_20-13-08_256.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0LOksHvxBjRWiuPyheWvxxxpgUB8tpG8qLYM1K6AbHdV_HowFcerC_BkidMRyBxWRDpfnQELgBFkuNTE5MifMu1oOdlod2kMlMEK8xqYLxIWIrf8r_DJgAG70a0xYK_oaeOAVhWEwNHPc/s320/2012-03-13_20-13-08_256.jpg" width="180" /></a>
</td><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih9LleekSbLrBsZFj-eYw8i2iU9gokdZvDCMH03esLh_z5VHd2rdEQONl6qdopecBZy_fzFioLnr3dUEO2UugFu0iMdHI55YnGr3TNZblclTmlw0hOzibJlqhQJLn57-neKvO_4CUJ2_uA/s1600/2012-03-13_20-13-14_775.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEih9LleekSbLrBsZFj-eYw8i2iU9gokdZvDCMH03esLh_z5VHd2rdEQONl6qdopecBZy_fzFioLnr3dUEO2UugFu0iMdHI55YnGr3TNZblclTmlw0hOzibJlqhQJLn57-neKvO_4CUJ2_uA/s320/2012-03-13_20-13-14_775.jpg" width="320" /></a>
</td></tr>
</tbody></table>
<br />
<b style="color: #990000;"></b>There was another molex connector hiding in the cabling. While fiddling with those wires in the 3rd picture, I noticed a loose molex inside the case. I don't know if it fell down or what, but with that plugged in fans and leds work. This one is black as opposed to the 2 opaque white ones - so if you don't have a black one plugged in, keep looking. Thermaltake told me there is a 4th molex as well, but I have not found that.<br />
<br />
<b>BIOS too old to POST</b><br />
<br />
Now, the issue appears to be that the motherboard shipped before it was technically able to run the chips they advertised it for. Everyone online is saying that I need to swap out the CPU with an older one long enough to upgrade the BIOS. Personally, I don't have another AM3 cpu and am kinda annoyed at the idea that I would have to buy a CPU that I would toss 5 minutes later. I emailed ASUS support - but I bet I am just delaying the inevitable.<br />
<br />
I did find <a href="http://www.tomshardware.com/forum/305557-30-upgrading-bios-sabertooth-990fx" target="_blank">this post</a> that mentions the BIOS being physically replaceable with this <a href="http://us.estore.asus.com/index.php?l=product_detail&p=3890" target="_blank">$15 part</a>. Looking at my board, I have confirmed that the BIOS is swappable - though it means draining the water cooling and removing the second video card (not something I look forward to trying right away).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5fC3nMo800cmiZXfM7pEHb1Wf_7AVwCL-mWe1QWw057gfBGdzttf2HNjBEr3HZ2fNv3YOJpAlpQUsHAyBEfStpdWtWNg4X0vE7E7EDMsNAb7TMaG8BzxWdLl8P6mwmXm3hjykznAkp53/s1600/2012-03-14_21-45-55_766.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju5fC3nMo800cmiZXfM7pEHb1Wf_7AVwCL-mWe1QWw057gfBGdzttf2HNjBEr3HZ2fNv3YOJpAlpQUsHAyBEfStpdWtWNg4X0vE7E7EDMsNAb7TMaG8BzxWdLl8P6mwmXm3hjykznAkp53/s320/2012-03-14_21-45-55_766.jpg" width="320" /></a></div>
<br />
I was going to wait until I had the board completely up and dual booting to post this -- but I have no idea how long it will take to get the BIOS replacement. I'll go ahead and push this out now, and once I have the BIOS replacement I'll update the blog. I definitely do not look forward to pulling out that 2nd GTX to swap the BIOS - but it's better than buying a throw-away CPU.<br />
<br />
<br />
<div style="color: #990000;">
<b>UPDATE:</b></div>
<br />
I have the system up and running... a brief recap of what I had to do...<br />
<ol>
<li>Replace the physical BIOS with the one listed above. This was a little harder than it should have been because I had to remove BOTH video cards to get to the BIOS since I have such a short watercooling tube between them. Also, my chip puller appears to be too big and I didn't have the patience to go to a store the following day, so I had to use my fingers instead. </li>
<li>After #1, the board wouldn't boot. Not even fans now. The BIOS came with instructions stating that you may need to reset the CMOS. Ok.</li>
<li>Tried the jumper first. No go.</li>
<li>Pulled both video cards again so that I could get to the battery. Reset the battery and the jumper at the same time. Let me tell you, if you are installing the new BIOS -- get it before putting the board together because removing both of these cards is not fun.</li>
<li>Woot! Boots into BIOS. Looked over the settings. I thought it seemed to be running a little hot (already at 89*F) but, I have never used water cooling before, so not sure what to expect.</li>
<li>Install Windows [yes, I know - but I need it for some of my games]. Install some driver CDs for the motherboard, network card, etc. Installed the EVGA drivers and upon reboot... wait, no, it wouldn't reboot. damn. CPU LED, DRAM LEEEEEDDDDDDDDDDDDDDDD... hmmm</li>
<li>MemOK button.</li>
<li>CPU LED, DRAM LED, VIDEO LED, repeat, repeat repeat repeat... damn</li>
<li>I contacted Asus who not only called me but gave me their email addresses so that I could get back in touch with them. Very professional. </li>
<li>Tried jumper again. No good. </li>
<li>Tried just 1 stick of memory. No good.</li>
<li>Tried removing SLI bridge (it was the evga drivers installed last, right?). No good.</li>
<li>Ok, let's try removing the video cards... as I went to pull them out, I noticed the network card is not sitting all the way down. I try to reseat it and notice it *won't* sit all the way down? WTF? Well, it came with another plate... checking - no that one is shorter... damn... pliers... bend faceplate... Ah, not it seats properly. Checking - hey! It boots.</li>
<li>Put everything together and test booting throughout. Everything is fine now.</li>
<li>Ok, with Windows installed, now let's install LMDE (Linux Mint Debian Edition).</li>
<li>Booting, live boot failure?... and black screen. Damn. </li>
<li>Some internet search and chats later (thanks Jon for finding it) I add 'nomodeset' to the grub boot command. It boots.</li>
<li>Install LMDE (with grub on the Windows drive). Reboot. Black screen. Damn.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx5rttC950VP34G8Nw-NV2yHEDQR0Nb4zWl5FlUE0ClfAmMTsYFLeFgyY4JAJ5P_vpe9Y2vSWBZG-LK_jXnghuxvwyGEkZi10_5PKkRz9Ny2syYyrl2ed-uqtQy4hQvj8sQwn0F8oKiPt/s1600/2012-03-24_09-37-08_483.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYx5rttC950VP34G8Nw-NV2yHEDQR0Nb4zWl5FlUE0ClfAmMTsYFLeFgyY4JAJ5P_vpe9Y2vSWBZG-LK_jXnghuxvwyGEkZi10_5PKkRz9Ny2syYyrl2ed-uqtQy4hQvj8sQwn0F8oKiPt/s320/2012-03-24_09-37-08_483.jpg" width="320" /></a></div>
</li>
<li>Saw <a href="http://techpatterns.com/forums/about1516.html" target="_blank">this post</a> and decided to make it permanent..</li>
</ol>
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">sudo su - root</span></div>
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">nano /etc/default/grub</span></div>
</blockquote>
And to make the change work even for recovery mode... <br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">GRUB_CMDLINE_LINUX="nomodeset"</span></div>
</blockquote>
And then to update it and reboot:<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">update-grub</span></div>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">reboot </span></span></blockquote>
And we're good to go. I have Windows 7 and LMDE dual booting now. Now it's time to re-install my entire development environment ;)<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-28028804301177033632012-02-18T09:27:00.000-08:002012-02-18T09:27:29.253-08:00AIDL Step 7: Using CallbacksWhat if we would like the service to callback into the client?<br /><br />Rather than repeating all the previous tutorials, let's just alter the v2 API. <i style="color: #cc0000;"><b>Note: In the real world, you should never do that as you need to remain backward compatible. </b></i>Since I know no one else is using the api, we'll cheat.<br /><br />First, let's create <span style="font-family: "Courier New",Courier,monospace;">API/src/main/java/org/eoti/android/test/apkextensions/api/v2/IServerCallback.aidl</span>:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.api.v2;</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">oneway interface IServerCallback {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> void message(String text);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">}</span></span></blockquote>
<br /><br />And update our <span style="font-family: "Courier New",Courier,monospace;">IServer.aidl</span>:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.api.v2;</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">import org.eoti.android.test.apkextensions.api.v2.Registration;</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">import org.eoti.android.test.apkextensions.api.v2.IServerCallback;</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">interface IServer</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">{</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> void register(inout Registration registration, IServerCallback cb);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> void unregister(in String registrationName, IServerCallback cb);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> String getServerIdentifier();</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">}</span></span></blockquote>
<br /><br />Recompile our API<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/API$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br /><br />Next, we update our server. Replace <span style="font-family: "Courier New",Courier,monospace;">createV2Binder()</span> with:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> final RemoteCallbackList<IServerCallback> callbacks = new RemoteCallbackList<IServerCallback>();</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> protected void broadcast(String message)</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> final int N = callbacks.beginBroadcast();</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> for(int i=0; i<N; i++)</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> try {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> callbacks.getBroadcastItem(i).message(message);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> } catch (RemoteException e) {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> // RemoteCallbackList will take care of removing dead objects</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> callbacks.finishBroadcast();</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> private IBinder createV2Binder()</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> return new IServer.Stub(){</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> @Override</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> public void register(Registration registration, IServerCallback cb) throws RemoteException {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> registrations.put(registration.getName(), registration);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> if(cb != null)</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> callbacks.register(cb);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> cb.message("Registration successful");</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> Log.d(TAG, "Registration received: " + registration.getName() + " v" + registration.getVersion());</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> broadcast(registration.getName() + " has entered the room");</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> @Override</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> public void unregister(String registrationName, IServerCallback cb) throws RemoteException {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> if(registrationName == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> registrations.remove(registrationName);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> if(cb != null)</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> cb.message("Unregistration successful");</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> callbacks.unregister(cb);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> Log.d(TAG, "Registration removed: " + registrationName);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> broadcast(registrationName + " has left the room");</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> @Override</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> public String getServerIdentifier() throws RemoteException {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> return TheServer.class.getName() + "#" + TheServer.this.hashCode();</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> };</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /></blockquote>
<br />And compile it<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/TheServer$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br /><br />Next, we'll update our v2 client...<br />In our <span style="font-family: "Courier New",Courier,monospace;">Client2/src/main/java/org/eoti/android/test/apkextensions/client2/Client2Activity.java</span>, add:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> private IServerCallback callback = new IServerCallback.Stub() {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> @Override</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> public void message(String text) throws RemoteException {</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> Log.d(TAG, "Message received: " + text);</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> };</span></span></blockquote>
<br />change:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">server.register(registration);</span></span></blockquote>
to:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">server.register(registration, callback);</span></span></blockquote>
<br />and change:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">server.unregister(REG_NAME);</span></span></blockquote>
to:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">server.unregister(REG_NAME, callback);</span></span></blockquote>
<br />Rebuild it<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/Client2$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br />Run Client1:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client1/.Client1Activity } from pid 127</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.server for service org.eoti.android.test.apkextensions.server/.TheServer: pid=846 uid=10045 gids={1015}</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">E/Client1 ( 546): Server bound</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client1/.Client1Activity: +726ms</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client1 ( 546): Server connected</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/TheServer( 846): Registration received from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client1 ( 546): Registered org.eoti.android.test.apkextensions.client1.Client1Activity</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client1 ( 546): Running tests...</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client1 ( 546): Tests done...</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/TheServer( 846): Registration removed from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">E/Client1 ( 546): Server unbound</span></span></blockquote>
<br />Run Client2:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">W/KeyCharacterMap( 546): No keyboard for id 0</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">W/KeyCharacterMap( 546): Using default keymap: /system/usr/keychars/qwerty.kcm.bin</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client2/.Client2Activity } from pid 127</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.client2 for activity org.eoti.android.test.apkextensions.client2/.Client2Activity: pid=856 uid=10047 gids={1015}</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">E/Client2 ( 856): Server bound</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Server connected: org.eoti.android.test.apkextensions.server.TheServer#1079096160</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Message received: Registration successful</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/TheServer( 846): Registration received: org.eoti.android.test.apkextensions.client2.Client2Activity v1.0alpha</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Message received: org.eoti.android.test.apkextensions.client2.Client2Activity has entered the room</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Registered org.eoti.android.test.apkextensions.client2.Client2Activity</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Running tests...</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Tests done...</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/TheServer( 846): Registration removed: org.eoti.android.test.apkextensions.client2.Client2Activity</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">D/Client2 ( 856): Message received: Unregistration successful</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">E/Client2 ( 856): Server unbound</span></span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client2/.Client2Activity: +931ms</span></span></blockquote>
<br /><br />This all looks good -- but why didn't Client1 announce when Client2 entered the room? <br />It's because Client1 is still using the old deprecated API.Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com1tag:blogger.com,1999:blog-8434264790761186593.post-54746047351986963422012-02-18T08:36:00.000-08:002012-02-18T09:28:11.598-08:00AIDL Step 6: Creating an updated client<span style="font-family: inherit; font-size: small;">Create our new module:</span>
<br />
<blockquote class="tr_bq">
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b><span style="background-color: yellow;">mvn archetype:generate -DarchetypeCatalog=http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml</span></b><br />[INFO] Scanning for projects...<br />[INFO] ------------------------------------------------------------------------<br />[INFO] Building extension test 1.0-SNAPSHOT<br />[INFO] ------------------------------------------------------------------------<br />[INFO] <br />[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ pom >>><br />[INFO] <br />[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ pom <<<<br />[INFO] <br />[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ pom ---<br />[INFO] Generating project in Interactive mode<br />[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)<br />Choose archetype:<br />1: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.kryten:kryten-archetype (kryten-archetype)<br /><span style="background-color: #cfe2f3;"><b>2</b>: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.galatea:galatea-archetype (<b>galatea-archetype</b>)</span><br />3: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.archtest:archtest-archetype (archtest-archetype)<br />Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : <b style="background-color: yellow;">2</b><br />Define value for property 'groupId': : <b style="background-color: yellow;">org.eoti.android.test.apkextensions.client2</b><br />Define value for property 'artifactId': : <b style="background-color: yellow;">Client2</b><br />Define value for property 'version': 1.0-SNAPSHOT: : <br />Define value for property 'package': org.eoti.android.test.apkextensions.client2: : <br />Confirm properties configuration:<br />groupId: org.eoti.android.test.apkextensions.client2<br />artifactId: Client2<br />version: 1.0-SNAPSHOT<br />package: org.eoti.android.test.apkextensions.client2<br /> Y: : <br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Using following parameters for creating project from Archetype: galatea-archetype:1.1-SNAPSHOT<br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.client2<br />[INFO] Parameter: artifactId, Value: Client2<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.client2<br />[INFO] Parameter: packageInPathFormat, Value: org/eoti/android/test/apkextensions/client2<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.client2<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.client2<br />[INFO] Parameter: artifactId, Value: Client2<br />[WARNING] Don't override file /home/malachi/work/apkextensions/Client2/src/main/android/res/values/strings.xml<br />[WARNING] Don't override file /home/malachi/work/apkextensions/Client2/src/main/android/res/layout/main.xml<br />[INFO] project created from Archetype in dir: /home/malachi/work/apkextensions/Client2<br />[INFO] ------------------------------------------------------------------------<br />[INFO] BUILD SUCCESS<br />[INFO] ------------------------------------------------------------------------<br />[INFO] Total time: 19.317s<br />[INFO] Finished at: Sat Feb 18 08:09:07 PST 2012<br />[INFO] Final Memory: 11M/245M<br />[INFO] ------------------------------------------------------------------------</span></span></blockquote>
<br />
<br />
Take care of the keystore and dependency...<br />
<br />
And replace our <span style="font-family: "Courier New",Courier,monospace;">Client2Activity</span>:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.client2;<br /><br />import android.app.Activity;<br />import android.content.ComponentName;<br />import android.content.Context;<br />import android.content.Intent;<br />import android.content.ServiceConnection;<br />import android.os.Bundle;<br />import android.os.IBinder;<br />import android.os.RemoteException;<br />import android.util.Log;<br />import org.eoti.android.test.apkextensions.api.v2.IServer;<br />import org.eoti.android.test.apkextensions.api.v2.Registration;<br /><br />public class Client2Activity extends Activity {<br /> private static String TAG = "Client2";<br /><br /> private static final String REG_NAME = Client2Activity.class.getName();<br /> private static final String REG_VERSION = "1.0alpha";<br /> private enum State{Unbound,Bound,Connected,Disconnected}<br /> private State state = State.Unbound;<br /> private IServer server;<br /><br /> private ServiceConnection connection = new ServiceConnection() {<br /> @Override<br /> public void onServiceConnected(ComponentName componentName, IBinder iBinder) {<br /> server = IServer.Stub.asInterface(iBinder);<br /> state = State.Connected;<br /> try {<br /> Log.d(TAG, "Server connected: " + server.getServerIdentifier());<br /> Registration registration = new Registration();<br /> registration.setName(REG_NAME);<br /> registration.setVersion(REG_VERSION);<br /> server.register(registration);<br /> Log.d(TAG, "Registered " + registration.getName());<br /> } catch (RemoteException e) {<br /> Log.e(TAG, "Unable to register", e);<br /> }<br /><br /> doTest();<br /> }<br /><br /> @Override<br /> public void onServiceDisconnected(ComponentName componentName) {<br /> state = State.Disconnected;<br /> server = null;<br /> Log.d(TAG, "Server disconnected");<br /> }<br /> };<br /><br /> private void bindServer()<br /> {<br /> switch(state)<br /> {<br /> case Bound:<br /> case Connected:<br /> case Disconnected:<br /> return;<br /> default:<br /> bindService(new Intent(IServer.class.getName()), connection, Context.BIND_AUTO_CREATE);<br /> state = State.Bound;<br /> Log.e(TAG, "Server bound");<br /> break;<br /> }<br /> }<br /><br /> private void unbindServer()<br /> {<br /> switch(state)<br /> {<br /> case Unbound:<br /> return;<br /> case Connected:<br /> try{<br /> server.unregister(REG_NAME);<br /> }catch(RemoteException e){<br /> Log.e(TAG, "Unable to unregister", e);<br /> }<br /> server = null;<br /> // fall through<br /> default:<br /> unbindService(connection);<br /> state = State.Unbound;<br /> Log.e(TAG, "Server unbound");<br /> break;<br /> }<br /> }<br /><br /> @Override<br /> public void onCreate(Bundle savedInstanceState) {<br /> super.onCreate(savedInstanceState);<br /> setContentView(R.layout.main);<br /> bindServer();<br /> }<br /><br /> @Override<br /> protected void onDestroy() {<br /> unbindServer();<br /> super.onDestroy();<br /> }<br /><br /> protected void doTest()<br /> {<br /> Log.d(TAG, "Running tests...");<br /> // @TODO add tests here<br /> Log.d(TAG, "Tests done...");<br /> unbindServer();<br /> }<br />}</span></span></blockquote>
<br />
Build it... run it...<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b style="background-color: yellow;">cd Client2</b></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/Client2$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client2/.Client2Activity } from pid 127<br />I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.client2 for activity org.eoti.android.test.apkextensions.client2/.Client2Activity: pid=697 uid=10047 gids={1015}<br />I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.server for service org.eoti.android.test.apkextensions.server/.TheServer: pid=705 uid=10045 gids={1015}<br />E/Client2 ( 697): Server bound<br />I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client2/.Client2Activity: +1s67ms<br />D/Client2 ( 697): Server connected: org.eoti.android.test.apkextensions.server.TheServer#1079078320<br />D/TheServer( 705): Registration received: org.eoti.android.test.apkextensions.client2.Client2Activity v1.0alpha<br />D/Client2 ( 697): Registered org.eoti.android.test.apkextensions.client2.Client2Activity<br />D/Client2 ( 697): Running tests...<br />D/Client2 ( 697): Tests done...<br />D/TheServer( 705): Registration removed: org.eoti.android.test.apkextensions.client2.Client2Activity<br />E/Client2 ( 697): Server unbound<br />I/ActivityManager( 61): No longer want com.android.settings (pid 155): hidden #16</span></span></blockquote>
<br />
<br />
So we get deprecated messages when Client1 connects and the additional functionality when Client2 connects.<br />
Client2 also has access to functionality that Client1 is unaware of.<br />
<br />
Next up, <a href="http://malsandroid.blogspot.com/2012/02/aidl-step-7-using-callbacks.html" target="_blank">AIDL Step 7: Using Callbacks</a>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-81094128827210207872012-02-18T08:34:00.000-08:002012-02-18T08:51:52.625-08:00AIDL Step 5: Upgrading the ServiceLet's update our service to handle an additional intent...<br />
<br />
First, in the <span style="font-family: "Courier New",Courier,monospace;">AndroidManifest.xml</span> it should now read:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> <service android:name=".TheServer"><br /> <intent-filter><br /> <action android:name="org.eoti.android.test.apkextensions.api.v1.IServer"/><br /> <action android:name="org.eoti.android.test.apkextensions.api.v2.IServer"/><br /> </intent-filter><br /> </service></span></span></blockquote>
<br />
Then, let's update <span style="font-family: "Courier New",Courier,monospace;">TheServer.java</span> to handle both old and new clients:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.server;<br /><br />import android.app.Service;<br />import android.content.Intent;<br />import android.os.IBinder;<br />import android.os.RemoteException;<br />import android.util.Log;<br />import org.eoti.android.test.apkextensions.api.v2.IServer;<br />import org.eoti.android.test.apkextensions.api.v2.Registration;<br /><br />import java.util.concurrent.ConcurrentHashMap;<br /><br />public class TheServer extends Service<br />{<br /> private static final String TAG = TheServer.class.getSimpleName();<br /> private ConcurrentHashMap<String, IBinder> binders = new ConcurrentHashMap<String, IBinder>();<br /> private ConcurrentHashMap<String, Registration> registrations = new ConcurrentHashMap<String, Registration>();<br /><br /> private IBinder createV2Binder()<br /> {<br /> return new IServer.Stub(){<br /> @Override<br /> public void register(Registration registration) throws RemoteException {<br /> if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.put(registration.getName(), registration);<br /> Log.d(TAG, "Registration received: " + registration.getName() + " v" + registration.getVersion());<br /> }<br /><br /> @Override<br /> public void unregister(String registrationName) throws RemoteException {<br /> if(registrationName == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.remove(registrationName);<br /> Log.d(TAG, "Registration removed: " + registrationName); }<br /><br /> @Override<br /> public String getServerIdentifier() throws RemoteException {<br /> return TheServer.class.getName() + "#" + TheServer.this.hashCode();<br /> }<br /> };<br /> }<br /><br /> private IBinder createV1Binder()<br /> {<br /> return new org.eoti.android.test.apkextensions.api.v1.IServer.Stub(){<br /> @Override<br /> public void register(org.eoti.android.test.apkextensions.api.v1.Registration registration) throws RemoteException {<br /> if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.put(registration.getName(), new Registration(registration));<br /> Log.d(TAG, "Registration received from deprecated client: " + registration.getName());<br /> }<br /><br /> @Override<br /> public void unregister(String registrationName) throws RemoteException {<br /> if(registrationName == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.remove(registrationName);<br /> Log.d(TAG, "Registration removed from deprecated client: " + registrationName);<br /> }<br /> };<br /> }<br /> <br /> public IBinder onBind(Intent intent) {<br /> if(intent == null) return null;<br /> String action = intent.getAction();<br /> if(action == null) return null;<br /> IBinder binder = binders.get(action);<br /> if(binder != null)<br /> return binder;<br /> <br /> if(org.eoti.android.test.apkextensions.api.v1.IServer.class.getName().equals(action))<br /> binder = createV1Binder();<br /><br /> if(IServer.class.getName().equals(action))<br /> binder = createV2Binder();<br /><br /> if(binder != null)<br /> binders.put(action, binder);<br /> <br /> return binder;<br /> }<br /><br /> @Override<br /> public void onDestroy() {<br /> registrations.clear();<br /> super.onDestroy();<br /> }<br />}</span></span></blockquote>
<br />
<br />
Make sure it all compiles...<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b style="background-color: yellow;">cd TheServer/</b></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/TheServer$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br />
<br />
And make sure the now deprecated client can still connect:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client1/.Client1Activity } from pid 127<br />I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.server for service org.eoti.android.test.apkextensions.server/.TheServer: pid=605 uid=10045 gids={1015}<br />E/Client1 ( 546): Server bound<br />I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client1/.Client1Activity: +671ms<br />D/Client1 ( 546): Server connected<br />D/TheServer( 605): Registration received from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity<br />D/Client1 ( 546): Registered org.eoti.android.test.apkextensions.client1.Client1Activity<br />D/Client1 ( 546): Running tests...<br />D/Client1 ( 546): Tests done...<br />D/TheServer( 605): Registration removed from deprecated client: org.eoti.android.test.apkextensions.client1.Client1Activity<br />E/Client1 ( 546): Server unbound</span></span></blockquote>
<br />
<br />
Next up, <a href="http://malsandroid.blogspot.com/2012/02/aidl-step-6-creating-updated-client.html" target="_blank">AIDL Step 6: Creating an updated client</a>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-91306173921125261852012-02-18T08:31:00.000-08:002012-02-18T08:50:31.330-08:00AIDL Step 4: Upgrading the APILet's create a new <span style="font-family: "Courier New",Courier,monospace;">API/src/main/java/org/eoti/android/test/apkextensions/api/v2/Registration.java</span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.api.v2;<br /><br />import android.os.Parcel;<br />import android.os.Parcelable;<br /><br />public class Registration<br />implements Parcelable<br />{<br /> private String name = "unset";<br /> private String version = "unset";<br /><br /> public static final Creator<Registration> CREATOR = new Creator<Registration>()<br /> {<br /> @Override<br /> public Registration createFromParcel(Parcel parcel) {<br /> return new Registration(parcel);<br /> }<br /><br /> @Override<br /> public Registration[] newArray(int size) {<br /> return new Registration[size];<br /> }<br /> };<br /><br /> public Registration()<br /> {<br /><br /> }<br /><br /> public Registration(Parcel in)<br /> {<br /> readFromParcel(in);<br /> }<br /><br /> public Registration(org.eoti.android.test.apkextensions.api.v1.Registration deprecated)<br /> {<br /> this();<br /> this.name = deprecated.getName();<br /> }<br /><br /> public void setName(String name){this.name = name;}<br /> public String getName(){return name;}<br /> public void setVersion(String version){this.version = version;}<br /> public String getVersion(){return version;}<br /><br /> @Override<br /> public int describeContents() {<br /> return 0;<br /> }<br /><br /> @Override<br /> public void writeToParcel(Parcel out, int flags) {<br /> out.writeString(getName());<br /> out.writeString(getVersion());<br /> }<br /><br /> public void readFromParcel(Parcel in)<br /> {<br /> setName(in.readString());<br /> setVersion(in.readString());<br /> }<br />}</span></span></blockquote>
<br />
<br />
You might be wondering why we don't extend the previous class. It's because of the<span style="font-family: "Courier New",Courier,monospace;"> final Creator</span> method. If you try to send a v2 registration across the previous AIDL, it will send it as a v1. Using a base class that they both extend would be doable - but I decided to keep the example simple.<br />
<br />
Create a new <span style="font-family: "Courier New",Courier,monospace;">API/src/main/java/org/eoti/android/test/apkextensions/api/v2/Registration.aidl</span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.api.v2;</span></span><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">parcelable Registration;</span></span></blockquote>
<br />
<br />
And let's create our new server API that contains some extra functionality...<br />
<span style="font-family: "Courier New",Courier,monospace;">API/src/main/java/org/eoti/android/test/apkextensions/api/v2/IServer.aidl</span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.api.v2;</span></span><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">import org.eoti.android.test.apkextensions.api.v2.Registration;</span></span><br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">interface IServer</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">{</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> void register(inout Registration registration);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> void unregister(in String registrationName);</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> String getServerIdentifier();</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">}</span></span></blockquote>
<br />
<br />
Make sure it all compiles...<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b style="background-color: yellow;">cd API</b></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/API$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br />
Next up, <a href="http://malsandroid.blogspot.com/2012/02/aidl-step-5-upgrading-service.html" target="_blank">AIDL Step 5: Upgrading the Service</a>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-77198155714662879562012-02-18T08:29:00.000-08:002012-02-18T08:49:01.695-08:00AIDL Step 3: Creating the Client<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b><span style="background-color: yellow;">mvn archetype:generate -DarchetypeCatalog=http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml</span></b><br />[INFO] Scanning for projects...<br />[INFO] ------------------------------------------------------------------------<br />[INFO] Building extension test 1.0-SNAPSHOT<br />[INFO] ------------------------------------------------------------------------<br />[INFO] <br />[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ pom >>><br />[INFO] <br />[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ pom <<<<br />[INFO] <br />[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ pom ---<br />[INFO] Generating project in Interactive mode<br />[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)<br />Choose archetype:<br />1: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.kryten:kryten-archetype (kryten-archetype)<br /><span style="background-color: #cfe2f3;"><b>2</b>: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.galatea:galatea-archetype (<b>galatea-archetype</b>)</span><br />3: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.archtest:archtest-archetype (archtest-archetype)<br />Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : <b style="background-color: yellow;">2</b><br />Define value for property 'groupId': : <b style="background-color: yellow;">org.eoti.android.test.apkextensions.client1</b><br />Define value for property 'artifactId': : <b style="background-color: yellow;">Client1</b><br />Define value for property 'version': 1.0-SNAPSHOT: : <br />Define value for property 'package': org.eoti.android.test.apkextensions.client1: : <br />Confirm properties configuration:<br />groupId: org.eoti.android.test.apkextensions.client1<br />artifactId: Client1<br />version: 1.0-SNAPSHOT<br />package: org.eoti.android.test.apkextensions.client1<br /> Y: : <br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Using following parameters for creating project from Archetype: galatea-archetype:1.1-SNAPSHOT<br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.client1<br />[INFO] Parameter: artifactId, Value: Client1<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.client1<br />[INFO] Parameter: packageInPathFormat, Value: org/eoti/android/test/apkextensions/client1<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.client1<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.client1<br />[INFO] Parameter: artifactId, Value: Client1<br />[WARNING] Don't override file /home/malachi/work/apkextensions/Client1/src/main/android/res/values/strings.xml<br />[WARNING] Don't override file /home/malachi/work/apkextensions/Client1/src/main/android/res/layout/main.xml<br />[INFO] project created from Archetype in dir: /home/malachi/work/apkextensions/Client1<br />[INFO] ------------------------------------------------------------------------<br />[INFO] BUILD SUCCESS<br />[INFO] ------------------------------------------------------------------------<br />[INFO] Total time: 25.201s<br />[INFO] Finished at: Sat Feb 18 07:32:17 PST 2012<br />[INFO] Final Memory: 13M/309M<br />[INFO] ------------------------------------------------------------------------</span></span></blockquote>
<br />
<br />
Take care of the keystore stuff in the pom...<br />
and add the dependency:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> <dependency><br /> <groupId>org.eoti.android.test.apkextensions.api</groupId><br /> <artifactId>API</artifactId><br /> <version>1.0-SNAPSHOT</version><br /> <type>apklib</type><br /> </dependency></span></span></blockquote>
<br />
edit your <span style="font-family: "Courier New",Courier,monospace;">Client1/src/main/java/org/eoti/android/test/apkextensions/client1/Client1Activity.java</span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.client1;<br /><br />import android.app.Activity;<br />import android.content.ComponentName;<br />import android.content.Context;<br />import android.content.Intent;<br />import android.content.ServiceConnection;<br />import android.os.Bundle;<br />import android.os.IBinder;<br />import android.os.RemoteException;<br />import android.util.Log;<br />import org.eoti.android.test.apkextensions.api.v1.IServer;<br />import org.eoti.android.test.apkextensions.api.v1.Registration;<br /><br />public class Client1Activity extends Activity {<br /> private static String TAG = "Client1";<br /><br /> private static final String REG_NAME = Client1Activity.class.getName();<br /> private enum State{Unbound,Bound,Connected,Disconnected}<br /> private State state = State.Unbound;<br /> private IServer server;<br /><br /> private ServiceConnection connection = new ServiceConnection() {<br /> @Override<br /> public void onServiceConnected(ComponentName componentName, IBinder iBinder) {<br /> server = IServer.Stub.asInterface(iBinder);<br /> state = State.Connected;<br /> Log.d(TAG, "Server connected");<br /> try {<br /> Registration registration = new Registration();<br /> registration.setName(REG_NAME);<br /> server.register(registration);<br /> Log.d(TAG, "Registered " + registration.getName());<br /> } catch (RemoteException e) {<br /> Log.e(TAG, "Unable to register", e);<br /> }<br /><br /> doTest();<br /> }<br /><br /> @Override<br /> public void onServiceDisconnected(ComponentName componentName) {<br /> state = State.Disconnected;<br /> server = null;<br /> Log.d(TAG, "Server disconnected");<br /> }<br /> };<br /><br /> private void bindServer()<br /> {<br /> switch(state)<br /> {<br /> case Bound:<br /> case Connected:<br /> case Disconnected:<br /> return;<br /> default:<br /> bindService(new Intent(IServer.class.getName()), connection, Context.BIND_AUTO_CREATE);<br /> state = State.Bound;<br /> Log.e(TAG, "Server bound");<br /> break;<br /> }<br /> }<br /><br /> private void unbindServer()<br /> {<br /> switch(state)<br /> {<br /> case Unbound:<br /> return;<br /> case Connected:<br /> try{<br /> server.unregister(REG_NAME);<br /> }catch(RemoteException e){<br /> Log.e(TAG, "Unable to unregister", e);<br /> }<br /> server = null;<br /> // fall through<br /> default:<br /> unbindService(connection);<br /> state = State.Unbound;<br /> Log.e(TAG, "Server unbound");<br /> break;<br /> }<br /> }<br /><br /> @Override<br /> public void onCreate(Bundle savedInstanceState) {<br /> super.onCreate(savedInstanceState);<br /> setContentView(R.layout.main);<br /> bindServer();<br /> }<br /><br /> @Override<br /> protected void onDestroy() {<br /> unbindServer();<br /> super.onDestroy();<br /> }<br /><br /> protected void doTest()<br /> {<br /> Log.d(TAG, "Running tests...");<br /> // @TODO add tests here<br /> Log.d(TAG, "Tests done...");<br /> unbindServer();<br /> }<br />}</span></span></blockquote>
<br />
<br />
Let's compile it<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b style="background-color: yellow;">cd Client1</b></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/Client1$<b> <span style="background-color: yellow;">mvn clean install</span></b></span></span></blockquote>
<br />
To verify it is working, watch logcat as you launch Client1<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">I/ActivityManager( 61): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.eoti.android.test.apkextensions.client1/.Client1Activity } from pid 127<br />I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.client1 for activity org.eoti.android.test.apkextensions.client1/.Client1Activity: pid=546 uid=10046 gids={1015}<br />I/ARMAssembler( 61): generated scanline__00000177:03515104_00001002_00000000 [ 87 ipp] (110 ins) at [0x445306f0:0x445308a8] in 538806 ns<br />I/ActivityManager( 61): Start proc org.eoti.android.test.apkextensions.server for service org.eoti.android.test.apkextensions.server/.TheServer: pid=554 uid=10045 gids={1015}<br />E/Client1 ( 546): Server bound<br />I/ActivityManager( 61): Displayed org.eoti.android.test.apkextensions.client1/.Client1Activity: +1s140ms (total +10h57m29s956ms)<br />D/Client1 ( 546): Server connected<br />D/TheServer( 554): Registration received: org.eoti.android.test.apkextensions.client1.Client1Activity<br />D/Client1 ( 546): Registered org.eoti.android.test.apkextensions.client1.Client1Activity<br />D/Client1 ( 546): Running tests...<br />D/Client1 ( 546): Tests done...<br />D/TheServer( 554): Registration removed: org.eoti.android.test.apkextensions.client1.Client1Activity<br />E/Client1 ( 546): Server unbound</span></span></blockquote>
<br />
<br />
If you'd like to recompile everything at once, you can also use a top-level POM:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"></project></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><?xml version="1.0" encoding="UTF-8"?><br /><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><br /> <modelVersion>4.0.0</modelVersion><br /> <groupId>org.eoti.android.test.apkextensions</groupId><br /> <artifactId>pom</artifactId><br /> <version>1.0-SNAPSHOT</version><br /> <packaging>pom</packaging><br /> <name>extension test</name><br /><br /> <modules><br /> <module>API</module><br /> <module>TheServer</module><br /> <module>Client1</module><br /> </modules><br /><br /> <build><br /> <plugins><br /> <plugin><br /> <groupId>org.apache.maven.plugins</groupId><br /> <artifactId>maven-dependency-plugin</artifactId><br /> <executions><br /> <execution><br /> <id>copy-dependencies</id><br /> <goals><br /> <goal>copy-dependencies</goal><br /> </goals><br /> <phase>package</phase><br /> <configuration><br /> <includeScope>runtime</includeScope><br /> </configuration><br /> </execution><br /> </executions><br /> </plugin><br /> </plugins><br /> </build><br /></project></span></span><span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"></span></span></blockquote>
<br />
Just make sure that if you do, you update it whenever adding new modules. IntelliJ will generally do that for you. Not sure about Eclipse.<br />
<br />
<br />
So far, so good. Now, let's try upgrading to a new version :)<br />
<br />
Next up, <a href="http://malsandroid.blogspot.com/2012/02/aidl-step-4-upgrading-api.html" target="_blank">AIDL Step 4: Upgrading the API</a>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0tag:blogger.com,1999:blog-8434264790761186593.post-17958275281019033912012-02-18T08:26:00.000-08:002012-02-18T08:46:48.949-08:00AIDL Step 2: Creating the Service<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b><span style="background-color: yellow;">mvn archetype:generate -DarchetypeCatalog=http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml</span></b><br />[INFO] ------------------------------------------------------------------------<br />[INFO] Building extension test 1.0-SNAPSHOT<br />[INFO] ------------------------------------------------------------------------<br />[INFO] <br />[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ pom >>><br />[INFO] <br />[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ pom <<<<br />[INFO] <br />[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ pom ---<br />[INFO] Generating project in Interactive mode<br />[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)<br />Choose archetype:<br />1: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.kryten:kryten-archetype (kryten-archetype)<br /><span style="background-color: #cfe2f3;"><b>2</b>: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.galatea:galatea-archetype (<b>galatea-archetype</b>)</span><br />3: http://repository-malachid.forge.cloudbees.com/public-snapshot/archetype-catalog.xml -> org.eoti.archtest:archtest-archetype (archtest-archetype)<br />Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : <b style="background-color: yellow;">2</b><br />Define value for property 'groupId': : <b style="background-color: yellow;">org.eoti.android.test.apkextensions.server</b><br />Define value for property 'artifactId': : <b style="background-color: yellow;">TheServer</b><br />Define value for property 'version': 1.0-SNAPSHOT: : <br />Define value for property 'package': org.eoti.android.test.apkextensions.server: : <br />Confirm properties configuration:<br />groupId: org.eoti.android.test.apkextensions.server<br />artifactId: TheServer<br />version: 1.0-SNAPSHOT<br />package: org.eoti.android.test.apkextensions.server<br /> Y: : <br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Using following parameters for creating project from Archetype: galatea-archetype:1.1-SNAPSHOT<br />[INFO] ----------------------------------------------------------------------------<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.server<br />[INFO] Parameter: artifactId, Value: TheServer<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.server<br />[INFO] Parameter: packageInPathFormat, Value: org/eoti/android/test/apkextensions/server<br />[INFO] Parameter: package, Value: org.eoti.android.test.apkextensions.server<br />[INFO] Parameter: version, Value: 1.0-SNAPSHOT<br />[INFO] Parameter: groupId, Value: org.eoti.android.test.apkextensions.server<br />[INFO] Parameter: artifactId, Value: TheServer<br />[WARNING] Don't override file /home/malachi/work/apkextensions/TheServer/src/main/android/res/values/strings.xml<br />[WARNING] Don't override file /home/malachi/work/apkextensions/TheServer/src/main/android/res/layout/main.xml<br />[INFO] project created from Archetype in dir: /home/malachi/work/apkextensions/TheServer<br />[INFO] ------------------------------------------------------------------------<br />[INFO] BUILD SUCCESS<br />[INFO] ------------------------------------------------------------------------<br />[INFO] Total time: 22.380s<br />[INFO] Finished at: Sat Feb 18 07:13:45 PST 2012<br />[INFO] Final Memory: 11M/245M<br />[INFO] ------------------------------------------------------------------------</span></span></blockquote>
<br />
<br />
In <span style="font-family: "Courier New",Courier,monospace;">TheServer/pom.xml</span> make whatever keysigning changes you need (or remove the keysigning as we did in the previous step)<br />
and then add the following dependency:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> <dependency><br /> <groupId>org.eoti.android.test.apkextensions.api</groupId><br /> <artifactId>API</artifactId><br /> <version>1.0-SNAPSHOT</version><br /> <type>apklib</type><br /> </dependency></span></span></blockquote>
<br />
Create <span style="font-family: "Courier New",Courier,monospace;">TheServer/src/main/java/org/eoti/android/test/apkextensions/server/TheServer.java</span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">package org.eoti.android.test.apkextensions.server;<br /><br />import android.app.Service;<br />import android.content.Intent;<br />import android.os.IBinder;<br />import android.os.RemoteException;<br />import android.util.Log;<br />import org.eoti.android.test.apkextensions.api.v1.IServer;<br />import org.eoti.android.test.apkextensions.api.v1.Registration;<br /><br />import java.util.concurrent.ConcurrentHashMap;<br /><br />public class TheServer extends Service<br />{<br /> private static final String TAG = TheServer.class.getSimpleName();<br /> private ConcurrentHashMap<String, IBinder> binders = new ConcurrentHashMap<String, IBinder>();<br /> private ConcurrentHashMap<String, Registration> registrations = new ConcurrentHashMap<String, Registration>();<br /><br /> private IBinder createV1Binder()<br /> {<br /> return new IServer.Stub(){<br /> @Override<br /> public void register(Registration registration) throws RemoteException {<br /> if(registration == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.put(registration.getName(), registration);<br /> Log.d(TAG, "Registration received: " + registration.getName());<br /> }<br /><br /> @Override<br /> public void unregister(String registrationName) throws RemoteException {<br /> if(registrationName == null) throw new RemoteException(); // API15 required for 'new RemoteException(string)'<br /> registrations.remove(registrationName);<br /> Log.d(TAG, "Registration removed: " + registrationName); }<br /> };<br /> }<br /> <br /> public IBinder onBind(Intent intent) {<br /> if(intent == null) return null;<br /> String action = intent.getAction();<br /> if(action == null) return null;<br /> IBinder binder = binders.get(action);<br /> if(binder != null)<br /> return binder;<br /> <br /> if(IServer.class.getName().equals(action))<br /> binder = createV1Binder();<br /> <br /> if(binder != null)<br /> binders.put(action, binder);<br /> <br /> return binder;<br /> }<br /><br /> @Override<br /> public void onDestroy() {<br /> registrations.clear();<br /> super.onDestroy();<br /> }<br />}</span></span></blockquote>
<br />
<br />
in <span style="font-family: "Courier New",Courier,monospace;">TheServer/src/AndroidManifest.xml</span><br />
replace:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><service android:name=".TheServer"/></span></span> </blockquote>
with:<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"> <service android:name=".TheServer"><br /> <intent-filter><br /> <action android:name="org.eoti.android.test.apkextensions.api.v1.IServer"/><br /> </intent-filter><br /> </service></span></span></blockquote>
<br />
<br />
Make sure it compiles...<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions$ <b style="background-color: yellow;">cd TheServer</b></span></span><br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">malachi@onyx:~/work/apkextensions/TheServer$ <b style="background-color: yellow;">mvn clean install</b></span></span></blockquote>
<br />
Next up, <a href="http://malsandroid.blogspot.com/2012/02/aidl-step-3-creating-client.html" target="_blank">AIDL Step 3: Creating the Client</a>Malachi de AElfwealdhttp://www.blogger.com/profile/09298673505665552268noreply@blogger.com0