Maybe you already know about ViewPager and are using something like ViewPagerIndicator by JakeWharton for indicating the title. Did you know that there is something doing that in the support library? If you use it, it looks like this:
Now how do you use this? First you need to set up your ViewPager. If you already know how to do that, please skip this part.
Setting up ViewPager
ViewPager is the Component that allows us swiping through Pages to the left and right. The best way to use a ViewPager is with Fragments. (If you do not know about Fragments yet, search for it on Google and read a little bit about it.)
To implement the ViewPager we need to do three things:
Let us look at the code to add the ViewPager to the layout:
So we use the ViewPager from the support library (make sure you have the support library in your libs folder or in the pom.xml if you use Maven).
Next we have to get the ViewPager, implement the Adapter and the Fragment. Here I implemented it in MainActivity.java:
As well we need the following xml which is used for the PageFragment:
There is some explanation needed here.
Now we the whole PagerAdapter should be working correctly. But how to get the nice headers? Continue reading.
Setting up PagerTabStrip
So you see we added the PagerTabStrip inside the ViewPager. You can play around with the colors if you like. If you just do this you will see the header, but no text. Because we did not tell the ViewPager yet what the titles are for each page. To do this we need to override getPageTitle(int position):
Once we implemented this we should see the titles correctly.
How to use with ActionBarSherlock or Maven
Problem with ActionBarSherlock and Maven is that there is only the old support library used/available. So using ActionBarSherlock for example we will not be able to find PagerTabStrip. You could just use PagerTitleStrip, but that might not be good enough for you. So what can you do? You can copy paste the code from PagerTitleStrip to your own source code. To do this without getting errors, do the following:
In the xml and java files use the same code as above, but with the PagerTabStrip2 instead of PagerTabStrip.
You want to have a nice report how much you cover with your Android unit tests? Here a quick walkthrough how to get such a report (see screenshots of report below).
In this example I expect that your test project is in a folder “tests” in your project folder which gets tested.
cd <main project folder>
android update project --path .
android update test-project -m <full path to main project> -p tests/
Somehow “.” does not work and you have to use the full path like “/home/pboos/develop/workspace/project”
This will print out the path to the html file where you can see a nice report. Should be in “tests/coverage/coverage.html”.
If you have libraries that you use and you get an error. Make sure you put them into a “libs” directory. ant automatically adds the libraries in “libs” to the build path.
Example for coverage report:
If you get an error, that emma.jar (or android) is not in your classpath, you might have forgotten to add the tools directory to your classpath. Follow the instructions below “How to update your PATH” on http://developer.android.com/sdk/installing.html#sdkContents. As well make sure that you have updated the Android SDK Tools (I used revision 11, when I wrote this). How to do this is here: http://developer.android.com/sdk/adding-components.html
What this tutorial will cover
I just got a free micro EC2 instance at AWS (Amazon Web Services) for 1 year for free (see here) and thought I could try out Scala and Lift on it. I did that once already to test, but this time I wanted a nicer installation. I wanted to use Jetty as Server that is always running on the ec2 instance. Then I want to be able to easily deploy .war files to it.
If you are on windows and you want to connect to your EC2 with Putty follow the instructions here.
To get a basic jetty version running on your server, do the following:
tar xfz jetty-distribution-$JETTY_VERSION.tar.gz
java -jar start.jar
There you go. Your basic jetty installation is running already! Put a .war file into the webapps folder and access it by adding the name of the war file to the url (.war => http://server.com// )
More information under http://wiki.eclipse.org/Jetty/
To install and run MongoDB on your own computer follow the instructions here: http://www.mongodb.org/display/DOCS/Quickstart (their explanation is perfect :) ) To install and run MongoDB on EC2 follow those instructions: http://www.mongodb.org/display/DOCS/Amazon+EC2 Here some links for starting with MongoDB on Scala:
Try “screen -S jetty” and then start Jetty there. To leave that “screen” press CTRL A + D. To see that screen again enter “screen -r jetty”. You can do the same with another name for MongoDB, just use “mongodb” instead of “jetty” in the command.
Easy deployment script (SCP)
Sometimes typing “sbt package” and “scp ……..” can be too much. :D So I wrote a small script that does the work for you. Create a file called deploy in the root of the sbt project, adjust the values below SETTINGS and make “chmod +x deploy”. After that you can run it with “./deploy”. Have fun :)
Sadly it does not show the SCP output :(. If you figure out how to do it, please let me know in the comments.
Maybe later we will go into writing a WebService: http://www.assembla.com/wiki/show/liftweb/REST_Web_Services
What this tutorial will cover
I will write down instructions for Mac OS X. But for Windows or Linux the instructions might only differ slightly.
Create basic lift project with SBT (Simple Build Tool)
With SBT we will be managing our lift project. It helps us to do several tasks pretty easy. The easiest way to start with Lift and SBT is to download a sample SBT Lift project from https://github.com/lift/lift_23_sbt . On that site click on “Downloads” on the right to download it as .tar.gz or .zip. Then choose one of the folders depending on what you want to do. You can choose lift_basic to see an example.
I prefer git and will handle my project with git so I do the following to download the default example:
git clone https://github.com/lift/lift_23_sbt.git
cp -R lift_23_sbt/lift_basic/ myLiftProject
now add a .gitignore with the content as [here] and then do
git add .
git commit -m "first commit"
Run the basic project
Go into the folder myLiftProject and rund the following commands. Some of them will take quite some time.
~jetty-run will start jetty to run your project. Go to http://127.0.0.1:8080/ and you will see the web site up and running. If you change anything in the code it will automatically notice that and compile it. A few seconds later you see the change reflected on the site. Use CTRL+C to stop it from executing.
If you want to package your project as a .war to put it on your web server, run “sbt package”.
Working on the code
Well there are several ways to work on the lift (scala) code. You can use vim, eclipse or IntelliJ IDEA. I will quickly explain how to work with eclipse and IntelliJ IDEA community edition (both free tools)
Install the ScalaIDE for Eclipse. Read more about it here: http://www.scala-ide.org/
Create a file called MySbtProjectPlugins.scala in project/plugins/ with the following content
IntelliJ IDEA (Community Edition)
Create a IntelliJ IDEA project out of the sbt project (full info here):
Read as well on http://liftweb.net/ (specially the getting started) to learn more about Lift.
You can use RUN@cloud as a lift server. You can currently get a basic account for free! Register and upload your .war file there.
With the next tutorials I will try to cover how to set up a nicer server with jetty and mongodb and then deploying the war file. Hopefully we can automate that as much as possible.
First of all let me start why I am writing this. I had a Nexus One for a long time already and love it (yes Gingerbread is already installed! Even before the OTA update - thanks to the cyanogenmod team). Because of my whole family using au I am using au as well. So I thought I buy the IS03 which is basically a good phone (hardware wise). BUT the software on the phone is far away from good. So I am pretty disappointed. And the problem is I can not make it faster myself. I am dependent on Sharp/KDDI. Why?
I refer to the Google statement [here]. Last paragraph reads:
Unfortunately, until carriers and manufacturers provide an easy method to legitimately unlock devices, there will be a natural tension between the rooting and security communities. We can only hope that carriers and manufacturers will recognize this, and not force users to choose between device openness and security. It’s possible to design unlocking techniques that protect the integrity of the mobile network, the rights of content providers, and the rights of application developers, while at the same time giving users choice. Users should demand no less.
So if you are open doesn’t mean you are not secure!
2. Having full control over all the phones
So you want to make sure people only have YOUR system installed. And that they do not do anything else than what you allow them to do? Do carriers/manufacturers think this is something that will HELP them? I think it will not help them at all. Some users (that do not know other Android phones) will get mad about this. But developers or people used to Android will notice things you do not allow them to do. And this results in bad news.
But now. If you let them control what they run, is that bad? You might think yes, because they will then abuse it for WiFi tethering and so on, which you do not want them to do. At first: How many of the customers will actually unlock their phone and go through the trouble to install a new system? Most fear they can’t do it or break their phone in so doing. I know a lot of developers who have a Android phones which can be easily unlocked and do not even unlock it because they do not want to go through the trouble or are okay with the phone how it is. And those who unlock it and install their own system will not use WiFi tether 24/7! They might not even use it at all! I had my Nexus One already rooted in Switzerland. I did use it for WiFi tether sometimes. But that was only in the train doing some work and surfing web pages (because it was easier from the PC to do that than from the phone). But it did not result in massive data load. But if I would not have traveled in the train so often, I would not have used WiFi Tethering at all.
So I guess there is no real reason for this point either.
I actually do not see how that will result in more money except keeping the data load down (which it doesn’t). But let me tell you how being open will lead to more money! :) Yes, you are right! Being open will help you in this area as well!
People will love your phone being open and start doing some interesting stuff. Maybe some really cool stuff that people will write about and that might come up in news papers! This is FREE ADVERTISEMENT! On the opposite. Being closed will just get some people angry which will lead to negative news which will not really help the phone to be sold and result in less money.
One way au is trying to make money is the au Market. Well. The idea itself is good. And being open won’t stop you from doing that. But honestly. I do not even use the au market on my phone. The Android Market app looks a lot better! Specially with the new update! And that is not only because I still have trouble reading Kanji!
4. Making the system look “au” stylish
Actually this is the part about the IS03 that I hate the most! Everything looks different than on my Nexus One. And it is not for the better, but for the worse. I do not like the colors, I do not like the Launcher (Home). The Launcher is sooo slow! I actually replaced it with “ADW.Launcher” which is close to the original and faster! The original even would be better than the Sharp/KDDI launcher! There are some widgets that I lose through doing this, but losing that is not as painful as what I lose using their launcher!
So this as well just makes users angry and won’t help you. And you invest tons of time to make it look like it is yours. And it won’t help that much. And then a new android version comes out and you think: “Okay, now let us port all that to the new version. It will take some months.” And there you go. Users are angry as well because they have to wait for the new update for too long! So just do not personalize it (or just very little)! It will make you have less work and the customers will be happy too! Isn’t it enough for you that they use your phone and are happy with it and therefore with you?
Here as well one small thing to KDDI: The KDDI Skype application is adding one small thing, but looking a lot worse than the original Skype! I prefer the original Skype application!
And you will even gain more!
People will use their free time to develop additional/better stuff for the phone and improve it. But of course for that to work Sharp would have to release their Source Code of the base system (which they should do anyway! HTC is doing it as well.). Open source developers will take that source and create additional stuff (see cyanogenmod for example - gives you not included radio fm support and lots of other things). And now how does Sharp gain from that? Most developers (if not all) will release their work in an open source project (https://github.com/cyanogenmod <— whole source code of cyanogenmod). And Sharp can than see how they did things and use the improvements in their updates to the regular users, which will profit from that as well.
Even Microsoft starts realizing that being open can help the company in the end. Read [here] where they allowed to have Kinect drivers being open sourced that everyone can play around with it! Here a small quote out of that article:
Microsoft also now seems to have recognised the innate potential of amateur programmers in developing new ideas for using the Kinect for gesture control and is now actively supporting them.
Wrapping it up
Dear manufacturers and carriers. Being open won’t make life worse for you! It will make your life better! It will make it FUN for you to see what happens and what you can gain without doing much and by just being open!
So do yourself and your customers the favor and be open!
While I am developing on Android there are some commands the android shell offers, that I just love. They are very helpful for debugging or testing some things. Let me share my favorites with you. If you have other ones you use often, please tell me those in the comments.
// starts the facebook app showing the inbox screen by using the Uri for thatadb shell am start -a android.intent.action.VIEW -d facebook://facebook.com/inbox
// open a vcard file from sdcard (will open contacts app :) )
adb shell am start -a android.intent.action.VIEW -d file:///sdcard/me.vcard -t text/x-vcard
// open an application to get content (in this case to get a jpeg picture)
adb shell am start -a android.intent.action.GET_CONTENT -t image/jpeg
Such commands in the adb shell are very usefull to launch intents. Just run “adb shell am” to see what other options you have and start playing around.
Show info about running activities (I use it to see the activity stack of my app)
adb shell dumpsys activity
This will dump out a lot of information like: Sticky broadcasts, Activity stack, Running processes.
Why would you want to reverse engineer a android application? Well there are different reasons:
Please do not use the info found here for illegal purposes. Respect the work of people who release good apps. Even if they cost! They need to get payed too!
What will we use?
We use apktool to do the tasks of getting the original (or nearly original) files and to rebuild the app after we did changes. Here info about apktool form the original site.
It is a tool for reengineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications; it makes possible to debug smali code step by step. Also it makes working with app easier because of project-like files structure and automation of some repetitive tasks like building apk, etc.
It is NOT intended for piracy and other non-legal uses. It could be used for localizing, adding some features or support for custom platforms and other GOOD purposes. Just try to be fair with authors of an app, that you use and probably like.
1. Install apktool
Version 1.3.2 has currently a pretty bad bug! All xmls with @ will have problems. But a fixed version can be found here.
Unpack both to /usr/local/bin (or windows folder on windows) 2. See the source code of the app (with source code I mean smali-code)
Get the .apk.
3. Rebuild the apk
Go into the source folder of the app. If you did it as above, than it will be the “out” folder. (cd out)
You will need to sign the apk (see more infos here). You can use your own or just quickly create a keystore like i did with this command:
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
Note that you will have to refer to the correct files (keystore and .apk).
apktool bjarsigner -verbose -keystore my-release-key.keystore dist/.apk alias_name
zipalign -v 4 dist/.apk dist/-aligned.apk
adb install dist/-aligned.apk
You need to uninstall because the signature will be different and it won’t let you overwrite the app.
Some words in the end
Well that’s was it! Not difficult right? If you have problems or questions, please write comments.
Cheers to Brut.all who developed apktool. And of course all the others involved!
As some of you might now I did an internship in Japan between July 1st and September 30st. I did it at a company called D&M Pearl which is located close to Shinjuku. It was a great time there. But what did I do in those three months you wonder? Specially because it is a pearl company you might wonder, what I could do there as a programmer. Well let me help you. I created a webshop for them. The shop is called pearls4girls. My internship ended at the end of September and I joined a new company called tonchidot in Shinjuku where I do Android programming.
Since I started working at the new company we finished the webshop and are ready to launch it! Feel free to check out the webshop located at http://pearls4girls.jp. And if you find something nice for your wife or girlfriend, don’t hesitate to buy it :).
Well some more technical info what I did for the webshop. I created the webshop using the community edition of Magento. It offers a great variety of features. I removed some of the features we didn’t need and added some features we did need like delivery date and time. There are a lot of modules for Magento. Some I could use, but for delivery date and time I had to do some more programming. Creating modules for Magento is kind of difficult. But after you learn how it works, it is actually pretty nice. But I still don’t know everything in Magento. What I really liked in Magento is the way you can design the website. It works with layouts and templates. Layouts are XML files that define what is shown on which page. Which boxes appear where and when. It is really flexible. And in the templates .phtml files you create the actual html design which can include php. And you can easily switch between different design. And that even in the same store! It is pretty nice. Even though we only created one design for our webshop.
Do you want to offer a free version of your Android app and as well a payed version without ads and more functionality but with the same basic features? I wanted to do so with my SleepTimer app (extended/unlocked version with Widget and no ads). But what can be problems to do so? Or what where problems that kept me from doing until now?
Well. I found a solution, that got me around all those problems above! Interested to hear? Continue reading. I will try to tell you enough on how to do that for your apps. You can find a working example by searching for SleepTimer.
Two versions in one (unlock app functionality) First let us toggle the problem of having two projects/apps to maintain. The solution is to only have one and implement all the functionality in it. And then we lock away the functionality for people who didn’t pay. We set one key (for example “is_app_payed”) in SharedPreferences to default false. When we have extended functionality we check if “is_app_payed” and if true, then we offer the functionality. Or with apps, if payed, then we don’t show them. Here a quick example how I hide the “Unlock” menu point in the Activity after the app has been paid:
In the next points I will explain how to get money for the app and then setting the “is_app_payed” in preferences to true.
Ways to pay for the app
There are three ways I am planning to offer for my app.
I got the PayPal app done already and will publish it soon to the market. If you need help with it, please write me. I might make another tutorial to explain how to make in-app payments possible with PayPal.
To unlock the app with those ways, the original app needs to discover the apps installed and maybe get information from them. For that I made a menu button “Unlock” which puts the user to the Activity which will check if anything of the above has been done, and then either unlocks the app (sets “is_app_payed” to true) or shows a screen with instructions and information.
1. Browser PayPal Donate
Here the user just does the payment through a donation button on the web, or a link in the app, that directs the user to the website to donate. You will receive the payment information and will have to do some work to help to get his app unlocked. Send the user the .apk file which is the same that other users buy in the Marked.
In the Unlock Activity of the original app, which can be reached through the menu button, you check if the package name of the payed app exists. If yes, then it sets “is_app_payed” to true and returns to the home screen. On the home screen I changed the Logo to the payed logo, so the user knows, that the app really is unlocked now.
Here some code out of my Unlock Activity to show how to detect if the other app is installed:
I think the code should explain itself :). But note that the app which is running this code and the unlock app need to have the same signature for the check above.
2. PayPal in app payment
This one is a little bit more difficult. 1st you have to create an application that will make an in-app payment to your account over PayPal.
This application you will put on the Android Market for free.
PayPal offers a PayPal SDK for Android which lets you build this app. In the app all you do is launch the payment activity of PayPal with the amount you want to get. When the amount is payed PayPal will tell your app and you set a var in this app to remember that the user already payed once through PayPal. Later this will get checked.
So that your original app can access this information there are different ways. I chose to offer a Activity to check that information. That Activity will be called through the original app through startActivityForResult(…)) and will get back the result if it was payed or not. The result can be immediate if it was payed. If it was not payed yet, you can display the app itself.
Now to some code on how to do this:
In your original app, which should get unlocked, you do the following in onCreate(…) to check and call the other app:
The missing code can be found above.
In the PayPal app you have to do the following in your AndroidManifest.xml to make the Activity, that checks the payment, available to your original program:
You notice, that ch.pboos.android.SleepTimerPayPal.CHECK is called with the Intent in the original app. So we need to make that Action lead us to the exported activity PayedDialogActivity.
Now this is basically it for the PayPal way.
3. Purchase app
The app mentioned in 1. Browser PayPal Donate is the same app you can release on the Android Market. If they buy this app it will be installed and result in the same as if they got the app from you as explained above.
I hope I was not too confusing. If you have any questions or suggestions, please comment!
Advanced Security (Make it more difficult to hack) velazcod mentioned in the comments, that this is really easy for users to hack. Might be a small percentage, but can influence your sales. Discussing with velazcod below and in chat we found a solution that is probably easiest and most effective. There is no code yet, but here the steps, that should tell you enough on what to do.
Of course you have to include your public key in the app. And nobody can fake the value in the preferences, because only you can do that with the private key.
The last few days I worked on getting translations to work with gettext. Somehow it didn’t work the way I wanted it. Big problem there is: You need to restart the server when you update translations. But I kind of liked the gettext style and tools that already exist.
Because of that I wrote my own class in PHP which allows me to get translations done on the future web site for an Android Project.
Here a quick example of code how it works:
Well. This is the website constructed. But now we need to create the .pot file for this website. Well. No problem. Just run the following command after you set the domain (setDomain). You can as well give an array of files if you have more than one file in the same domain.
This will create the locale/test.pot through running a shell command (xgettext needs to be installed). You have to do this for every domain you create through the website. Best is probably to make a .php file which has all the domains with its files. Than you can run this once and get all the files done.
Now you can take that file and copy it to your language folder with the ending .po. For example we place it into “locale/de/LC_MESSAGES/test.po”. This is the same way as you would do with gettext. And in this file you can do your translations for German.
Gettext always compiles things. So I thought why should I not do the same? Instead of always read through the entire .po file and filling the array I could just do that once. So I did. When you compile the file will be read, filled into an array and then serialized. The following command will do that for all files in locale:
Well that’s it. And don’t forget, that the whole locale folder needs to be writable :).
Here I give you my example files to test it out.
If you have any questions or improvements, let me know in the comments :).