Sunday, July 20, 2014

Android - SuppressLint cannot be resolved to a type

After upgrading my Android SDK 20 and ADT-23.0.2, some projects got error "SuppressLint cannot be resolved to a type"

I fixed this by

1. In project property -> Android, change to another API level and change back.
2. change the order in project property ->Java build path -> Order and Export.
3. also please try refresh and clean the project.

Hope it can help and save some hours.

Tuesday, July 08, 2014

OpenDrive cloud storage direct link

I am trying OpenDrive storage service.
You will get 5G storage, and 1G traffic for a basic account.
It is great that you can share file by direct link.
I think it is very useful for a developer.
We can put XML, JSON, image files on the OpenDrive for testing.

Go to their website and have a look:

Wednesday, January 22, 2014

Setup DNSmasq MAC DNS server

$ brew install dnsmasq

$ cp /usr/local/opt/dnsmasq/dnsmasq.conf.example /usr/local/etc/dnsmasq.conf
$ sudo cp -fv /usr/local/opt/dnsmasq/*.plist /Library/LaunchDaemons
$ sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist

Go to System Network preference,
Set the only one DNS as


#upstream dns servers

#for the host domain to the ip, like the "hosts" file

# set listen address as your IP


Put upstream server in /etc/resolv.dnsmasq.conf , such as
nameserver upstream_dns_server

Kill the process, it will restart and reload new config.

$ sudo kill $(ps aux | grep '[d]nsmasq' | awk '{print $2}')


Install DNSmasq locally on Mac OS X via Homebrew

Setup a wildcard TLD using Dnsmasq on OS X


 ps aux  : to see every process on the system using bSD syntax;

$ ps aux 
timothy  29217  0.0  0.0 11916 4560 pts/21   S+   08:15   0:00 pine 
root     29505  0.0  0.0 38196 2728 ?        Ss   Mar07   0:00 sshd: can [priv]  
can      29529  0.0  0.0 38332 1904 ?        S    Mar07   0:00 sshd: can@notty 
USER = user owning the process
PID = process ID of the process
%CPU = It is the CPU time used divided by the time the process has been running.
%MEM = ratio of the process’s resident set size to the physical memory on the machine
VSZ = virtual memory usage of entire process
RSS = resident set size, the non-swapped physical memory that a task has used
TTY = controlling tty (terminal)
STAT = multi-character process state
START = starting time or date of the process
TIME = cumulative CPU time
COMMAND = command with all its arguments
ps -aux VS ps aux

Note that "ps -aux" is distinct from "ps aux". The POSIX and UNIX standards require that "ps -aux" print all processes owned by a user named "x", as well as printing all processes that would be selected by the -a option. If the user named "x" does not exist, this ps may interpret the command as "ps aux" instead and print a warning. This behavior is intended to aid in transitioning old scripts and habits. It is fragile, subject to change, and thus should not be relied upon.

Thursday, October 17, 2013

Fix Android cannot show Logcat, "Invalid Argument"

Fix problem: Android cannot show Logcat, "Invalid Argument"
  • Unplug and plug your device
  • Switch ON/OFF the developer option – USB debugging
  • Clicking at the device on DDMS-Device tab
  • Use command "adb logcat -c" followed by unplug/plug device.
  • On DDMS-Device tab, click the down triangle, choose “Reset adb”
  • Huawei device: *#*#2846579#*#*  Go ProjectMenu / Background Setting / Log setting
  • Use app to show logcat, such as CatLog (
  • Run “echo 1 > /sys/kernel/logger/log_main/enable” in “adb shell”
Reference :

Sunday, September 22, 2013

Use Launch Daemon to Start Tomcat Automatically on Mac

Start tomcat automatically on Mac.

1. create at tomcat/bin
2. create /Library/LaunchDaemons/org.apache.tomcat.plist
3. restart your mac

Note: Replace "/Users/username/tomcat" with your tomcat path in and plist file.

try to launch tomcat with the plist
"sudo launchctl load -w /Library/LaunchDaemons/org.apache.tomcat.plist"

If you got error: "launchctl: Dubious ownership on file (skipping)" [5]
Please try change owner and permission of the plist file
a. change the owner to root with "sudo chown root <filename>",
b. change the permissions with "sudo chmod 644 <filename>"
   (4 for read access, 2 for write access, 1 for execute access, added up. The first number is for the owner, the second for the group, the third for everyone.) 

----- ---------

Tuesday, August 20, 2013

Batch rename images to sequence number with script

To get some test images.
Get images from, as follows,

create a shell script (.sh) file with following content

for file in *.jpg; do
    n=$(( $n+1 ))
    mv $file $file_name

Images are renamed to sequence number

Monday, August 05, 2013

iOS handle Remote Push Notification

There are three cases to handle remote push notification.
  1. Your app was just launched
    handle callback didFinishLaunchingWithOptions application launched by clicking "View" when app is not running
  2. Your app was just brought from background to foreground
    by clicking "View" when app is running in background.
    handle callback didReceiveRemoteNotification
  3. Your app was already running in the foreground
    handle callback didReceiveRemoteNotification
Both (2) and (3) are handled by didReceiveRemoteNotification, use the following code to distinguish forground and background.

Thursday, August 01, 2013

Using Ti.Google.Analytics in Titanium Mobile

In previous post "Titanium Javascript Execution Context", we know that different javascript execution context == different scopes. When implementing the Google Analytics, we will meet this problem.

The Ti.Google.Analytics project has been converted to use CommonJS. [1]

var gaModule = require('Ti.Google.Analytics'); var analytics = new gaModule('UA-XXXXXX-X'); // Call the next function if you want to reset the analytics to a new first time visit. // This is useful for development only and should not go into a production app. //analytics.reset(); // The analytics object functions must be called on app.js otherwise it will loose it's context Ti.App.addEventListener('analytics_trackPageview', function(e){
analytics.trackPageview('/iPad' + e.pageUrl); }); Ti.App.addEventListener('analytics_trackEvent', function(e){ analytics.trackEvent(e.category, e.action, e.label, e.value); }); // Starts a new session as long as analytics.enabled = true // Function takes an integer which is the dispatch interval in seconds analytics.start(10,true); // You don't need to call stop on application close, but this is just to show you can callstop at any time (Basically sets enabled = false) Titanium.App.addEventListener('close', function(e){ analytics.stop(); });
By using commonJS, all of our windows are in same context, we can simply call analytics.trackPageview directly inside windows.

However, for windows created by window.url property, the global variable "analytics" is not available.  For compatible reason, in window created by "url" property, we can still fire a global event to track.  Like this,

    Ti.App.fireEvent("analytics_trackPageview", {pageUrl:'myhomepage'});

Titanium Javascript Execution Context

Some notes from "Understanding Execution Contexts"

"A JavaScript application running in a web browser is single threaded and has a global variable scope for the entire application. A Titanium Mobile application is similar"

app.js creates one execution context.

" New execution contexts are created when a window is created that points to an external JavaScript file, which would then bootstrap the new window."
We call it "heavyweight" window.

var win = Titanium.UI.createWindow({
  title: 'New Window',
  url: 'win.js'

"When this new window is opened, it will have it’s own context and scope, so any variables declared in other contexts will not be available."

The variable defined in app.js is out of scope in win.js, because it's another execution context.

You can fire application-level events that will be received in all currently active execution contexts (app.js plus any open windows) via fireEvent. Custom events can have arbitrary data passed along with them, as shown in the example below:

Ti.App.fireEvent('myCustomEvent', {
  myCustomEventValue: 'someValue'

"You can listen for these custom events in any context by using addEventListener at the application level as well. The example below listens for our custom event – you’ll notice that any properties of the object passed as the second argument to fireEvent are available on the event object the callback function takes as an argument:"

Ti.App.addEventListener('myCustomEvent', function(event) {'You sent me: '+event.myCustomEventValue);

"Note that only ACTIVE execution contexts will receive a custom event when it is sent, so any windows that are not yet open will not receive the event."

Thursday, May 16, 2013

SVN create and switch to branch

Mac OS X 10.8.2
svn, version 1.6.18 (r1303927)

I want to work a new svn branch. And try the following comment

svn copy svn://server/path/trunk/project_name svn://server/path/branches/new_branch

But it's not ok. It returns error message:

"svn: Could not use external editor to fetch log message; consider setting the $SVN_EDITOR environment variable or using the --message (-m) or --file (-F) options
svn: None of the environment variables SVN_EDITOR, VISUAL or EDITOR are set, and no 'editor-cmd' run-time configuration option was found"

The command MUST have comment message like this

svn copy svn://server/path/trunk/project_name svn://server/path/branches/new_branch -m "create new branch"

The result is the project is copy to 


The we can go to the working copy and switch to the new branch by

 svn switch svn://server/path/branches/new_branch/project_name

Everything is ok. You modification to the old working copy is still there.

The --relocate option of switch causes svn switch to do something different: it updates your working copy to point to the same repository directory, only at a different URL (typically because an administrator has moved the repository to another server, or to another URL on the same server).[1]