It’s that time of the year again, another Ubuntu upgrade.
I wanted to document some of the things I find myself repeatedly having to do
on a fresh install of Ubuntu, as the unfortunately the upgrade process can be
very hit and miss. (Thankfully if you keep /home mounted on a separate
partition reinstalling is fairly painless).
gsettings set org.gnome.desktop.wm.preferences button-layout \
":minimize,maximize,close"
Set the power button to suspend
1
gsettings set org.gnome.settings-daemon.plugins.power button-power 'hibernate'
I also like to:
Swap Esc and Capslock
Set the ‘lid close’ action to ’Do Nothing’
Add a ‘hotedge’ using unity-tweak-tool (previously ccsm) to spread windows.
Set my open terminal shortcut to Ctrl-F12
Issues this time round
13.04 doesn’t seem to like my HP ProBook 6555b’s Mobility Radeon HD 4225/4250.
On booting I was met with a garbled display, the mouse moved but that was it
(radeon driver).
Strangely, booting into recovery, then selecting continue boot from there
seemed to bring up the desktop ok.
My solution to this has been to move back to 12.10’s kernel, 3.5.0-17.
Update, kernel 3.9 fixes it!
With the help of some kind contributers, both
Glimmr and
Roidrage
are each translated into 11 languages between them, including German, Finnish,
Japanese, Dutch, Russian, Sweedish, Danish, Spanish, Portugese, Polish, and
Slovenian.
Managing these isn’t the easiest job in the world. Some people mention
services such as http://www.getlocalization.com/, which seem decent, but come
with two problems as far as I can see:
They’re not free, which for a low/no profit app isn’t very ideal.
They require sign up, and have somewhat of a learning curve.
Point 2. is the main problem for me. I don’t want to assume a level of
expertise on my translator. They may speak 5 languages flawlessly, but haven’t
a clue about xml, or have the time to create an account on a new site and learn
it’s ins and outs.
A solution
What you can safely assume about most people however, is that they have used
some form of a spreadsheet before. If they are offering to translate an
Android app, it’s likely they already have a Google account.
So what I do is create a Google Doc, and invite them to
update it with their translations.
Step 1) Generating your doc
I’ve put together a couple of Python scripts to help manage these. The first thing you’ll want to do is ‘seed’ your spreadsheet with the source language (English in most cases).
123
$ git clone git://github.com/brk3/android-scripts.git
$ cd android-scripts
$ ./get_strings.py your-project/res/values/strings.xml
This will parse the strings from your default strings.xml and dump them stdout.
You can then copy these to your doc.
Step 2) Importing a new set of translations back into your app
Once someone has added a column by translating the first one into their
language, you can generate a strings.xml for that using the following steps:
This will write a file called /tmp/output.xml. The script will also perform
some basic checks and fixups on the translations vs. the source strings,
including:
Missing linebreak characters
Swaps 2-3 dots for the ellipses unicode character (as recommended by Android
lint guidelines)
Will bail if there are an uneven number of source strings vs. translated
ones. (Missing translations are acceptable but there must be a blank line
present to indicate this. Otherwise it’s likely there’s a mismatch.)
Inspect it to make sure you’re happy with the results, then copy it to
res/values-de/strings.xml.
Summary
Obviously this process leaves a lot to be desired. There’s still way too many
manual steps. The above scripts were put together out of necessity and not
much else. I definitely think there’s room for a good project here, to somehow
interact with Google docs from Python and generate all languages automatically.
So far I’ve preferred to put the time into app code rather than extend this
kind of tooling. If you like the general idea though and would like to add
improvements no matter how small, please submit a pull request to the
android-scripts github.
A while back, around the time Marissa Mayer took over Yahoo, a site popped up
with the message:
“Dear Marissa Mayer, PLEASE MAKE flickr AWESOME AGAIN”.
I’ve got into photography lately, and awesome or not, Flickr still seems to be
the go to place for hobbyist photographers. Unfortunately the official Android
app for Flickr was disappointing. Sure, it’s fairly functional, but it’s
execution of a lot of this felt dated, the interface is slow and just not what
I look for in an Android app.
I had been working on a Twitter app for about
3 months for much the same reasons as above, and it seems I wasn’t the only one
to feel this way as recently the surge of new holo themed Twitter apps has been
massive. Some of these already far surpassed my vision for my app, and so
rather than trying to play catch up, I gave up. Shortly after, I took some of
the work that had gone into my Twitter app and morphed it into
Glimmr.
I’m really thrilled to say so far the reaction has been pretty great. Thanks
for reading, enjoy the app!
The JavaImp plugin for Vim can add and organise imports in Java files at the
press of a button. One thing that it’s missing however, is a way to find and
remove redundant imports.
Here’s one solution I’ve come up with and would like to share; there may be
neater ways but as a first pass I’ve found this works quite well.
First install the ‘checkstyle’ package:
1
$ sudo apt-get install checkstyle
Secondly, download the following
script and save it
under ~/bin/clean_imports.sh
Finally, add the following to your .vimrc:
1234567
" F7 to call clean redundant Java imports and sort them
function JavaImpClean()
%!~/bin/clean_imports.sh %
:JavaImpSort
endfunction
:command JavaImpClean exec JavaImpClean()
:nnoremap <F7> :JavaImpClean<CR>
Just hit F7 when editing any Java and have your imports cleaned and sorted. I’m
sure with some more time this could be adapted to use a variety of code
checkers to work with different languages.
Now all I need is a way to pull in all missing imports without having to go
through each one…
I recently managed to procure myself a Galaxy Nexus, and so started looking
into how much it takes to apply 4.0 stylings to my app.
Surprisingly this can be easier than you think! Read on to find out how.
Before and after:
The easy way:
If you’re lucky, it can be as easy as changing one line, and rebuilding with
the latest sdk.
Provided you don’t have too much custom styling applied, try adding the
following to your AndroidManifest.xml:
1
<uses-sdkandroid:targetsdkversion="15"/>
If you leave the minSdkVersion as is, it should still work as always on pre ICS
devices, but automatically apply ‘Holo’ theme on devices running 4.0.
If you’re unlucky / things to watch out for:
Getting a successful build after the above change is the ideal scenario. If
you’re unlucky, your app may require a little more work to port.
As an example, I’ve recently ported the open source market app ‘Kitchen Timer’.
This presented two problems:
1. The NumberPickers:
The current version of
Kitchen Timer uses NumberPicker widgets, which were not officially available
pre-ICS. These are now available since api 11, but in order to get these to
update their style, I had to swap out each use of the custom NumberPicker
instances and replace them with android.widget.NumberPicker, as well as update
a couple of api calls.
An unfortunate effect of a change like this is that the app is now no longer
compatible with pre-ICS.
2. The ActionBar
As I’ve quickly found out, there are no option menus in ICS, which have been
since replaced by either a items on an ActionBar, or an overflow button on the
button bar for backwards compatibility reasons.
This is fine, except that the ActionBar can take up layout space that your
original design may not have accounted for.
I ended up removing two buttons from the Kitchen Timer to allow all three
timers to be controlled with one button.
Summary:
That’s about it, if you’re lucky, just increasing your targetSdkVersion and
rebuilding with the latest sdk will be enough to instantly modernise your app.
Hopefully by having read the above you can save time by jumping over some of
the more common pitfalls associated with this process.
Extra Reading:
You can also look at taking ports further with some of Jake Wharton’s fantastic
backwards compatible libraries such as ActionBarSherlock, and
ViewPagerIndicator.
Like many things in Java/Android, writing multitouch enabled applications in
Android can require quite a bit boilerplate code. It also requires quite a bit
of knowledge of the workings of multitouch, and how the points are tracked by
the api. This can make it tedious for new developers to get started with
implementing this kind of functionality.
Much of the above can be avoided by using Luke
Hutchison’s android-multitouch-controller.
It still requires some boilerplate, however it takes care of a lot of the
headaches around properly implementing operations such as pinch-to-zoom,
pinch-to-scale, pinch-to-rotate, etc., and lets you get on with the rest of
your app.
I’ve found it quite extendable, and it provides a good basis for those needing
to implement a more advanced multitouch tracking. I’ve also made use of it
extensively for my app
RoidRage, so
thought I could share some examples on how to get started with using this
library.
importorg.metalev.multitouch.controller.MultiTouchController;importorg.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;importorg.metalev.multitouch.controller.MultiTouchController.PointInfo;importorg.metalev.multitouch.controller.MultiTouchController.PositionAndScale;importorg.metalev.multitouch.controller.MultiTouchController.MultiTouchEntity;importorg.metalev.multitouch.controller.MultiTouchController.ImageEntity;publicclassDemoViewextendsViewimplementsMultiTouchObjectCanvas<MultiTouchEntity>{privateMultiTouchController<Object>multiTouchController=newMultiTouchController<Object>(this);publicDemoView(Contextcontext,AttributeSetattrs){super(context,attrs);}@OverridepublicvoidselectObject(MultiTouchEntitye,PointInfotouchPoint){}@OverridepublicbooleansetPositionAndScale(MultiTouchEntitye,PositionAndScalenewImgPosAndScale,PointInfotouchPoint){returntrue;}@OverridepublicvoidgetPositionAndScale(MultiTouchEntitye,PositionAndScaleobjPosAndScaleOut){}@OverridepublicMultiTouchEntitygetDraggableObjectAtPoint(PointInfopt){returnnull;}@OverridepublicbooleanonTouchEvent(MotionEventevent){returnmultiTouchController.onTouchEvent(event);}// rest of my code..}
The first thing you’ll probably notice about the above is the template type T
given to the MultiTouchObjectCanvas. This can be any class you want, depending
on how you want to interact with your canvas. In most cases, people will
probably be interested in manipulating images, so my fork of this library
contains two new classes, MultiTouchEntity, and a subclass called ImageEntity.
ImageEntity is a small subclass of MultiTouchEntity, which can be used to hold
an image to be managed by multitouch.
Let’s see how we can add some images to our above example using ImageEntity:
importorg.metalev.multitouch.controller.MultiTouchController;importorg.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;importorg.metalev.multitouch.controller.MultiTouchController.PointInfo;importorg.metalev.multitouch.controller.MultiTouchController.PositionAndScale;importorg.metalev.multitouch.controller.MultiTouchController.MultiTouchEntity;importorg.metalev.multitouch.controller.MultiTouchController.ImageEntity;publicclassDemoViewextendsViewimplementsMultiTouchObjectCanvas<MultiTouchEntity>{privateMultiTouchController<MultiTouchEntity>multiTouchController=newMultiTouchController<MultiTouchEntity>(this);privateArrayList<MultiTouchEntity>mImages=newArrayList<MultiTouchEntity>();privatestaticfinalint[]IMAGES={R.drawable.m74hubble,R.drawable.catarina,R.drawable.tahiti,R.drawable.sunset,R.drawable.lake};publicDemoView(Contextcontext,AttributeSetattrs){super(context,attrs);Resourcesres=context.getResources();for(inti=0;i<IMAGES.length;i++){mImages.add(newImageEntity(IMAGES[i],res));mImages.get(i).load(context,50.0f,50.0f);}}@OverridepublicvoidselectObject(MultiTouchEntitye,PointInfotouchPoint){if(img!=null){// Move image to the top of the stack when selectedmImages.remove(img);mImages.add(img);}else{// Called with img == null when drag stops.}invalidate();}@OverridepublicbooleansetPositionAndScale(MultiTouchEntitye,PositionAndScalenewImgPosAndScale,PointInfotouchPoint){booleanok=((ImageEntity)img).setPos(newImgPosAndScale);if(ok)invalidate();returnok;}@OverridepublicvoidgetPositionAndScale(MultiTouchEntitye,PositionAndScaleobjPosAndScaleOut){objPosAndScaleOut.set(img.getCenterX(),img.getCenterY(),(mUIMode&UI_MODE_ANISOTROPIC_SCALE)==0,(img.getScaleX()+img.getScaleY())/2,(mUIMode&UI_MODE_ANISOTROPIC_SCALE)!=0,img.getScaleX(),img.getScaleY(),(mUIMode&UI_MODE_ROTATE)!=0,img.getAngle());}@OverridepublicMultiTouchEntitygetDraggableObjectAtPoint(PointInfopt){floatx=pt.getX(),y=pt.getY();intn=mImages.size();for(inti=n-1;i>=0;i--){ImageEntityim=(ImageEntity)mImages.get(i);if(im.containsPoint(x,y))returnim;}returnnull;}@OverridepublicbooleanonTouchEvent(MotionEventevent){returnmultiTouchController.onTouchEvent(event);}// rest of my code..}
Again for simple purposes it’s possible that the amount of boilerplate could be
stripped down further, but if you have a read through it’s fairly self
explanatory.
The above code has been mostly extracted from the demo application that ships
with the library, ‘MTPhotoSorter’, which I recommend at least building and
installing this to get a feel for what’s possible with the library.
That’s about it for now, I can follow up this post with a few more tips and
examples if anyone finds it useful.
It’s been about two and a half months since I started work on my first Android
app, and I’m proud to say I’ve finally managed to get it out.
Have to say I’ve really enjoyed it from start to finish, and hope it will be
the first of many :) Here’s hoping it actually works for people and at least
someone manages to have some fun with it.
If you’re reading this for the first time thanks for stopping by, I’ll try to
keep update here a little more frequently with news of any updates. For the
dev interested folk I may also try and find time to write up on some of the
trickier issues I encountered along the way.
That’s all for now, check out my app and leave it 5 stars, you know you want to
;)
It’s a little ironic that given Android is one of the easier platforms to
pirate software, it’s also one of the platforms I don’t mind paying for
software. An app I’ll pay for generally meets the following criteria:
I use it multiple times a day, and will continue to over a long period.
The developer appears responsive to users regarding features/support.
It’s a reasonable price (in my opinion this is generally less than €1.99).
It looks good and has an intuitive interface.
The last point is probably the main one and something I think is unfortunately
lost on a lot of developers. It’s fair to say many programmers aren’t good
graphic designers. Good is obviously also a subjective term.
Enter the Android UI Guidelines. Google have taken the time to concisely write
up guidelines on how an app should look and feel, the benefits of which should
be obvious. Do they stifle creativity or prevent an app from looking distinct?
No. But what they will do is help users feel at ease using your app from the
get go, and help them run great on as many different devices as possible.
It really frustrates me to see people recommending an app so highly only to
download it on my Desire HD to be met with stretched out low res icons,
ignoring the use of the dedicated Android hardkeys with ever present settings
menus etc.
Apple have a very similar set of guidelines for developing iOS apps, yet they
seem to suffer far less from this issue. I don’t think the old cliche of
fragmentation is at fault here at all, more developers not wishing to follow
standards.
Perhaps Google could be a little better at regulating the marketplace also,
particularly as the Android tablets start to launch.
Google have just released a nice extension for Chrome for filtering or blocking
certain sites from appearing in search results.
What makes this different from just a hosts file or adblock is that it takes
the most blocked sites and sends them back to Google for analysis.
The first thing that came to my mind was the numerous crappy one click hoster
“link” sites that seem to consistently manage to make it into the top search
results as long as you search rapidshare+anything.
Most people however seem to be glad that this might finally mean the end of
sites such as experts-exchange.com. This seems to appear in a surprisingly
frequent number of programming related searches, only to infuriate the answer
seeker with a subscription fee for the answer.
What a lot of people still don’t know though, is if you scroll right down to
the bottom on these pages, the answer was there all a long for free :)
TL;DR version:
Scroll down to the bottom on experts-exchange for the answer.
Welcome to my blog. I like the thought of putting some of my
thoughts/experiences down in writing, not so sure about the making it public
part!
As I continually begin to get drawn in to use more and more services on the
web, I hope I can also use this to amalgamate my various profiles into one
place.
I’m already quite impressed with some of the fun things people are doing with
bloggerjekyll so will see how it goes :)