Archive for April, 2010
Short story: I received a free Nexus One (HTC) from Google for having an application on the android market with over 5000 downloads and a rating above 3.5 (For Counter-Strike 1.6 soundboard)
Back Story
Got a questionable email from Google (02/03/2010 23:47):
Subject: Device Seeding Program for Top Android Market Developers
From: android-market-seeding@google.comDue to your contribution to the success of Android Market, we would like to present you with a brand new Android device as part of our developer device seeding program. You are receiving this message because you’re one of the top developers in Android Market with one or more of your applications having a 3.5 star or higher rating and more than 5,000 unique downloads.
In order to receive this device, you must click through to this site, read the terms and conditions of the offer and fill out the registration form to give us your current mailing address so that we can ship your device.
You will receive either a Verizon Droid by Motorola or a Nexus One. Developers with mailing addresses in the US will receive either a Droid or Nexus one, based on random distribution. Developers from Canada, EU, and the EEA states (Norway, Lichtenstein), Switzerland, Hong Kong, Taiwan, and Singapore will receive a Nexus One. Developers with mailing addresses in countries not listed above will not receive a phone since these phones are not certified to be used in other countries.
We hope that you will enjoy your new device and continue to build more insanely popular apps for Android!
Thanks,
Eric Chu
Android Mobile PlatformGoogle, Inc.
1600 Amphitheater Parkway
Mountain View, CA 94043NOTE: You have received this mandatory email to notify you about an important update to the status of your Android account.
Initially I thought this was a scam, and searched the internet to check. Thankfully I came across a thread in Google forums of other people also sceptical about this email however it turned out to be legitimate (also confirmed by romainguy and others on twitter)
I then got a confirmation (06/03/2010):
Subject:Android Market Device Seeding Program Confirmation
From: Android Market Device Seeding ProgramDear Matthew,
We’ve received your information for the Android Market Device Seeding Program and have successfully validated the Google Order Number from your developer account.
Your information will now be sent to our shipping partner for order processing. Just to confirm, the information we received from you was:
Matthew RollingsIf you need to make any changes to your information above, please contact us at android-market-seeding@google.com as soon as possible. Otherwise, you should receive your phone in 2-4 weeks!
On behalf of the Android team,
Thanks, and happy coding!
Google, Inc.
1600 Amphitheater Parkway
Mountain View, CA 94043
I then received phone the phone on 29/04/2010 ~11:10. This is a lot later (3 weeks and 6 days) than the 2-4 weeks estimated for delivery, however this is believed to have been the fault of the shipping company Google were using.
Photos
Note: I will probably update this post with better photos and photos of the phone in action, or possibly even give a review of how awesome the phone is (and also how to get the internet working on o2 UK).
Cryptograms are enjoyable puzzles created from a saying or phrase encrypted with a substitutional cipher. They can be fun to decipher by hand by looking for common letter combinations, doublets, guesswork, and other flaws in this encryption mechanism.
I wrote a quick python script which will accept an input text and create a random substitutional cipher and encrypt it. It then outputs the cipher alphabet and the encrypted text.
Source code:
# -*- coding: utf-8 -*- import sys from random import randint from string import maketrans if (len(sys.argv)>1): # Normal alphabet alphabet="abcdefghijklmnopqrstuvwxyz" # Randomly create a new cipherbet cipherbet="" left=alphabet for i in range(0,len(alphabet)): x=randint(0,len(left)-1) cipherbet+=left[x] left=left[:x]+left[x+1:] # Get input text to translate text=sys.argv[1].lower() trantab = maketrans(alphabet,cipherbet) text=text.translate(trantab) # Replace unused letters in cipherbet with _'s for i in cipherbet: if i not in text: cipherbet=cipherbet.replace(i,"_") # Print cipherbet (solution) and the text (cryptogram) print cipherbet print text
Example usage
python create_cipher.py “The Science gets done. And you make a neat gun. For the people who are still alive.”
b_lpievrm_acqxuj_fzdgwn_o_
dri zlmixli vidz puxi. bxp oug qbai b xibd vgx. euf dri jiujci nru bfi zdmcc bcmwi.
Here is a quick tip for better organisation of your program by grouping all onClickListeners into a simple switch statement.
The problem
If you have lots of buttons or view that you are linking to OnClickListener events you can quickly end up with some cumbersome code. This can be changed very simply by implementing a method in your activity and switching between View ID’s.
Below is an example the typical method for creating an OnClickListener for a View.
final ImageButton Ibutton = (ImageButton) findViewById(R.id.button_1);
Ibutton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(testActivity.this, "Button 1 pressed ", Toast.LENGTH_SHORT).show();
}
});
final ImageButton Ibutton2 = (ImageButton) findViewById(R.id.button_2);
Ibutton2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(testActivity.this, "Button 2 pressed", Toast.LENGTH_SHORT).show();
}
});
The Solution
We can get our activity to handle the OnClick events itself, we do this we implementing OnClickListener:
public class testActivity extends Activity implements OnClickListener {
If your write this in eclipse you can hover over the error this produces and click Add unimplemented methods to automatically create a stub for the next part.
We now create our buttons similar to before, but for the setOnClickListener we pass this as an argument, so that our implemented method is called.
ImageButton Ibutton = (ImageButton) findViewById(R.id.button_1); Ibutton.setOnClickListener(this); ImageButton Ibutton2 = (ImageButton) findViewById(R.id.button_2); Ibutton2.setOnClickListener(this);
We now create the implemented method for our activity (onClick) and we use a switch statement to find which View fired the onclick event and preform an action accordingly.
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button_1:
// action to preform on button 1
Toast.makeText(testActivity.this, "Button 1 pressed ", Toast.LENGTH_SHORT).show();
break;
case R.id.button_2:
// action to preform on button 1
Toast.makeText(testActivity.this, "Button 2 pressed ", Toast.LENGTH_SHORT).show();
break;
}
}
And it’s as simple as that!
Feel free to post comments or questions
I received several requests regarding how I created a context menu (the menu activated on a long press) using a gridview and how to call functions such as saving a sound file from this. So I have created a quick example to explain this:
Tutorial
To implement a context menu (long press menu) you first need to include the following imports:
import android.view.ContextMenu; import android.view.View; import android.view.ContextMenu.ContextMenuInfo;
We start a very simple project, with the layout having a single button named button_example:
We then use registerForContextMenu in the onCreate of the activity to tell android that we want this view to create a menu when it is long pressed. This is not limited to buttons, this will work for other views too. You must register each view that you want to have associated with the context menu.
Button btn = (Button) findViewById(R.id.button_example); registerForContextMenu(btn);
You then need to override the onCreateContextMenu method to create the menu:
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context Menu");
menu.add(0, v.getId(), 0, "Action 1");
menu.add(0, v.getId(), 0, "Action 2");
}
And override onContextItemSelected to preform the action when an option is selected from this menu:
@Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Action 1"){function1(item.getItemId());}
else if(item.getTitle()=="Action 2"){function2(item.getItemId());}
else {return false;}
return true;
}
function1 and function2 are just place-holders at the moment that toast a message when they are used. In the above example we are choosing between Action 1 and Action 2 which define which function will be run when an item is selected. We have passed the ID of the view through the context menu and into this function so we can tell what the user was pressing when the context menu was created.
Examples
If you create a gridview and give each item a unique ID then you can use this method to preform actions based on each item. This is the method I use for my soundboard applications to save the sounds to the SD card as a notification or ringtone:
Source
Below is the source code:
package com.contextmenu.test;
import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.Button;
import android.widget.Toast;
public class test extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button_example);
registerForContextMenu(btn);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context Menu");
menu.add(0, v.getId(), 0, "Action 1");
menu.add(0, v.getId(), 0, "Action 2");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Action 1"){function1(item.getItemId());}
else if(item.getTitle()=="Action 2"){function2(item.getItemId());}
else {return false;}
return true;
}
public void function1(int id){
Toast.makeText(this, "function 1 called", Toast.LENGTH_SHORT).show();
}
public void function2(int id){
Toast.makeText(this, "function 2 called", Toast.LENGTH_SHORT).show();
}
}
I like using samba as a password-less method for people on a network to share and access files on my computer. This works well on a network you trust like a small home network or a small private network, however on different networks restricted access is preferred.
For me this problem is solved by simply having a button to turn samba on and off. This will also have the side effect that you will not be able to access anyone else’s shares but is sufficient for my needs.
Bash script
#!/bin/bash smb=`sudo /etc/init.d/samba status | grep running | wc -l` if [ $smb -gt 0 ] then # Stop samba sudo /etc/init.d/samba stop else # Start samba sudo /etc/init.d/samba restart fi
Where username is replaced with your username.
The script simply checks the status of samba to see if it is running, if it is then it is killed otherwise it is started. kdialog is used to display a notification of which toggle state we are in.
Adding a notification (KDE)
#!/bin/bash smb=`sudo /etc/init.d/samba status | grep running | wc -l` if [ $smb -gt 0 ] then # Stop samba sudo /etc/init.d/samba stop sudo -u username kdialog --passivepopup 'Samba off' 3 else # Start samba sudo /etc/init.d/samba restart sudo -u username kdialog --passivepopup 'Samba on' 3 fi
We run kdialog through `sudo -u username` because when the script is run with sudo the current user will be root, and using this will cause kdialog to display an ugly notification.
For an example of this try running `sudo kdialog “ugly message” 3`
As opposed to `sudo -u username kdialog –passivepopup ‘lovly message’ 3`
Creating an icon/button (KDE)
You can then turn this into a button you can simply click my creating a desktop file. In KDE Right click > new > link to application. Then fill in the application tab with the information as in the following image:
In the General tab you can give the button a name and choose the icon of your choice, click OK, and now you can drag your button to where ever you want it (taskbar, desktop, panel etc.) Then you can simple push the button to toggle samba on and off.
As you may or may not be aware some printers add extra information in order for the printer to be identified (primarily for counterfeiting case I believe). With colour laser printers this can be in the form of a small array of yellow dots printed onto you paper. Yellow dots are hardly visible to the naked eye, however if you are close enough and get the light at the right angle you can see them. If you have some blue leds or a blue light available this can make it much easier to see the dots (as the yellow dots will absorb the blue and look black).
Now much clearer under blue led illumination:
Unfortunately I my camera isn’t good enough quality and it doesn’t have a macro lens or feature so I can only show images at both extremes. Below are images captured with my microscope, you don’t have to look very far around the page, as the clusters are littered all over the page.
The Electronic frontier foundation have more information about the dots and have setup an address you can send a print test page to in order for them to build up a public defence case. Perhaps criminals will end up printing with yellow backgrounds to combat this method?
This is a nice colour laser printer that I managed to pick up quite cheaply with 2 sets of toner.
Problem
On my system (kubuntu 9.10 x86_64) it did not appear in lsusb and dmesg showed the following:
[15208.550014] usb 1-6: new high speed USB device using ehci_hcd and address 10
[15208.701200] usb 1-6: configuration #1 chosen from 1 choice
[15208.741575] usblp0: USB Bidirectional printer dev 10 if 0 alt 0 proto 2 vid 0x413C pid 0×5516
[15208.741596] usbcore: registered new interface driver usblp
[15209.747326] usb 1-6: usbfs: interface 0 claimed by usblp while ‘usb’ sets config #1
Funnily enough it did appear in the list of devices in virtualbox, however I had no luck trying (and didn’t really want to) to install it virtually. So I decided I’d make use of the built in network abilities of the printer and plug it directly into the router (I didn’t do this initially as I wanted the printer in a different room to the router).
Solution
After setting the printer up on the network, I ensure logged into the web interface and changed the password from the default. I then followed this thread on the ubuntuforums which refers to this text for installing the “Fuji Xerox DocuPrint C525A” driver which is compatible with the dell 1320c.
The driver is an 32bit rpm by default (which is fine for redhat based os’s), you can use alien to convert the rpm to an deb, or you can just download a prebuilt deb from zoffix.com (Direct link. This is a 32 bit package still so we need to install it using “–force-architecture”
sudo dpkg -i fuji-xerox-docuprint-c525-a-ap_1.0-2_i386.deb –force-architecture
Once this driver is installed you can login to cups and configure your printer as you would normally (instructions below). However when you are required to select the printer you need to provide the ppd file manually if you have installed the driver
1 – Open a webbrowser and goto http://localhost:631/admin
2 – Click add printer
3 – Enter a name for the printer eg: dell1320c (spaces are not allowed)
4 – Enter the printer address. This is the ip address of your printer prefixed with “lpd://”. eg: lpd://192.168.1.121
5 – Either locate Fuji Xerox DocuPrint C525A or select the ppd directly which is located at /usr/share/cups/model/FujiXerox/en/FX_DocuPrint_C525_A_AP.ppd
6 – Memory Capacity should be 64MB, and Optional Tray Module should be 250 Sheet Feeder
7 – finish.
Bypass tray problem
You should now print a test page, however if you get the problem like me that the printer always attempts to load paper from the manual paper feed, you will need to change the paper source from bypass tray to tray 1 in each program you need to print with (hopefully there will be a fix for this, but in this cups there seems no option to set it)
Additional
I also noticed that this printer was covering each printed page with tiny yellow dots, which can be used to identify a printer (most likely for criminal matters).























