( ! ) Deprecated: Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers. in /var/www/html/wp-includes/functions.php on line 6131
Call Stack
#TimeMemoryFunctionLocation
10.0000484224{main}( ).../index.php:0
20.0000484576require( '/var/www/html/wp-blog-header.php ).../index.php:17
30.15694941680require_once( '/var/www/html/wp-includes/template-loader.php ).../wp-blog-header.php:19
40.15794971000include( '/var/www/html/wp-content/themes/twentyfifteen/archive.php ).../template-loader.php:125
50.15794971000get_header( $name = ???, $args = ??? ).../archive.php:19
60.15794971216locate_template( $template_names = [0 => 'header.php'], $load = TRUE, $load_once = TRUE, $args = [] ).../general-template.php:48
70.15804971312load_template( $_template_file = '/var/www/html/wp-content/themes/twentyfifteen/header.php', $load_once = TRUE, $args = [] ).../template.php:749
80.15804971856require_once( '/var/www/html/wp-content/themes/twentyfifteen/header.php ).../template.php:814
90.15814979264wp_head( ).../header.php:18
100.15814979264do_action( $hook_name = 'wp_head' ).../general-template.php:3197
110.15814979480WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
120.15814979480WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
130.15835101248wp_enqueue_scripts( '' ).../class-wp-hook.php:341
140.15835101248do_action( $hook_name = 'wp_enqueue_scripts' ).../script-loader.php:2311
150.15835101464WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
160.15835101464WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
170.15855108984twentyfifteen_scripts( '' ).../class-wp-hook.php:341
180.15865110504wp_style_add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../functions.php:440
190.15865110504WP_Styles->add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../functions.wp-styles.php:245
200.15865110504WP_Dependencies->add_data( $handle = 'twentyfifteen-ie', $key = 'conditional', $value = 'lt IE 9' ).../class-wp-styles.php:385
210.15865110504_deprecated_argument( $function_name = 'WP_Dependencies->add_data()', $version = '6.9.0', $message = 'IE conditional comments are ignored by all supported browsers.' ).../class-wp-dependencies.php:317
220.15865110824wp_trigger_error( $function_name = '', $message = 'Function WP_Dependencies->add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:5925
230.15875111576trigger_error( $message = 'Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:6131

( ! ) Deprecated: Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers. in /var/www/html/wp-includes/functions.php on line 6131
Call Stack
#TimeMemoryFunctionLocation
10.0000484224{main}( ).../index.php:0
20.0000484576require( '/var/www/html/wp-blog-header.php ).../index.php:17
30.15694941680require_once( '/var/www/html/wp-includes/template-loader.php ).../wp-blog-header.php:19
40.15794971000include( '/var/www/html/wp-content/themes/twentyfifteen/archive.php ).../template-loader.php:125
50.15794971000get_header( $name = ???, $args = ??? ).../archive.php:19
60.15794971216locate_template( $template_names = [0 => 'header.php'], $load = TRUE, $load_once = TRUE, $args = [] ).../general-template.php:48
70.15804971312load_template( $_template_file = '/var/www/html/wp-content/themes/twentyfifteen/header.php', $load_once = TRUE, $args = [] ).../template.php:749
80.15804971856require_once( '/var/www/html/wp-content/themes/twentyfifteen/header.php ).../template.php:814
90.15814979264wp_head( ).../header.php:18
100.15814979264do_action( $hook_name = 'wp_head' ).../general-template.php:3197
110.15814979480WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
120.15814979480WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
130.15835101248wp_enqueue_scripts( '' ).../class-wp-hook.php:341
140.15835101248do_action( $hook_name = 'wp_enqueue_scripts' ).../script-loader.php:2311
150.15835101464WP_Hook->do_action( $args = [0 => ''] ).../plugin.php:522
160.15835101464WP_Hook->apply_filters( $value = '', $args = [0 => ''] ).../class-wp-hook.php:365
170.15855108984twentyfifteen_scripts( '' ).../class-wp-hook.php:341
180.18695112680wp_style_add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../functions.php:444
190.18695112680WP_Styles->add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../functions.wp-styles.php:245
200.18695112680WP_Dependencies->add_data( $handle = 'twentyfifteen-ie7', $key = 'conditional', $value = 'lt IE 8' ).../class-wp-styles.php:385
210.18695112680_deprecated_argument( $function_name = 'WP_Dependencies->add_data()', $version = '6.9.0', $message = 'IE conditional comments are ignored by all supported browsers.' ).../class-wp-dependencies.php:317
220.18695113000wp_trigger_error( $function_name = '', $message = 'Function WP_Dependencies->add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:5925
230.18705113224trigger_error( $message = 'Function WP_Dependencies-&gt;add_data() was called with an argument that is <strong>deprecated</strong> since version 6.9.0! IE conditional comments are ignored by all supported browsers.', $error_level = 16384 ).../functions.php:6131

Ten Amazing Java Applications

Java is such a great language and platform for any kind of application. It is open, fast, powerful, runs on any platform, and there are more jobs for Java than any other programming language. After reading more FUD and Java bashing from Ruby land I thought it would be fun to put together a list of truly amazing uses of Java that covers a wide spectrum.


 


10 – Sun SPOT


The Sun SPOT Device is a small, wireless, battery powered experimental platform. It is programmed almost entirely in Java to allow regular programmers to create projects that used to require specialized embedded system development skills. The hardware platform includes a range of built-in sensors as well as the ability to easily interface to external devices. The SPOT Development Kit contains two complete, free-range Sun SPOTs (with processor, radio, sensor board and battery) and one basestation Sun SPOT (with processor and radio). Also included are all the software development tools and cables required to start developing applications for your Sun SPOT.


 


 


9 – Project Looking Glass


Project Looking Glass is an open source development project based on and evolved from Sun Microsystems’ advanced technology project. It supports running unmodified existing applications in a 3D space, as well as APIs for 3D window manager and application development. At the moment, existing application integration is supported for Solaris x86 and Linux platforms. The library for 3D application development is available for Linux, Solaris and Windows.


 


 


8 – Flying Saucer & Mozilla Rhino


Flying Saucer is 100% Java XHTML+CSS renderer, including support for table pagination, margin boxes, running elements, named pages, and more. It is CSS 2.1 compliant (currently working on CSS 3 compliance), can be embedded into your Swing applications, and uses the open source LGPL license. This is a very impressive library! Equally impressive is Mozilla Rhino. Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically embedded into Java applications to provide scripting to end users. Imagine combining Flying Saucer, Applets/JavaFX Script support, Rhino, and the hugely improved “Consumer JRE”!


 


 


7 – UltraMixer


UltraMixer is a DJ mixing software which enables you to mix digital music in various formats such as MP3, WMA, AAC, OGG, WAV or CDs in real time. All you need is a sound card. The DJ’s turntables are replaced by two digital SoundPlayers, the “vinyls” are available within seconds through the integrated FileArchive. There are three versions of UltraMixer available: the Free Edition and the Basic Edition for private users and the Professional Edition for high demands and commercial use. It can interface with a number of hardware controllers so you don’t have to use a mouse.


 


 


6 – Blu-ray BD-J


The Blu-ray Disc Association (BDA) selected Java technology to be used as the platform for their advanced interactive application specification. Java technology was selected because:



  • Java technology has proven to be a technically sound solution in the mobile domain and in interactive television (MHP/OCAP)
  • Java technology has proven cross-platform technology support in embedded devices
  • Java technology provides an open-ended platform for content development with secure network support

I have seen a live demo of BD-J at JavaOne and was very impressed. Blu-ray seems to be winning the battle. It might finally be time to pick up a Blu-ray player.


 


 


5 – JavaFX Script & JavaFX Mobile


JavaFX Script is a compiled declarative scripting language that will soon be built into Java that enables Java developers and graphics designers to create rich user interfaces comparable to Adobe Flash. Recently key-frame animation support was added. The graphical designer tool being developed will be an Adobe Illustrator plugin. Rich Internet Applications built using JavaFX Script will run in the browser as an applet. An effort of cosmic proportions has been done to the Java Runtime Environment to improve startup time and responsiveness of applets.


 


JavaFX Mobile is a complete mobile operating and application environment built around Java and Linux open source technologies. JavaFX Mobile includes support for Java ME applications and other standard Java APIs to enable a broad range of new and existing Java applications. I think JavaFX Mobile brings a nearly complete Java SE environment to mobile devices (minus some things such as Corba, JMX, etc). Sun is a bit late in the game, but I think this will really pick up. I know I would prefer a full Java RIA over Adobe Flex.


 


4 – NASA World Wind


World Wind lets you zoom from satellite altitude into any place on Earth. Leveraging Landsat satellite imagery and Shuttle Radar Topography Mission data, World Wind lets you experience Earth terrain in visually rich 3D, just as if you were really there. It is very much like Google Earth, but written 100% in Java. There is an SDK for embedding it into your Java Swing applications.


 


 


3 – Team Jefferson’s Tommy Junior bot


Tommy Jr. is based on a Scion xB vehicle platform. The team’s secret weapon is the patent pending MAX software platform from Perrone Robotics. MAX represents the DNA and core robotics operating system that enables the rapid drop-in of commercially available and affordable sensors, hardware, and actuators. MAX is based 100% on Sun Microsystems’ Java technology. Tommy Junior’s micro-controllers and single low-cost standard car PC run the MAX robotics platform atop of standard, micro, and Java Real Time System (Java RTS) profiles.


The team’s after-market drop-in approach enables any vehicle whatsoever to be made fully autonomous within a short period of time. Tommy Junior’s cost in parts has been a mere $50,000 which includes the automotive platform itself. After actuators and hardware were dropped in, Tommy Junior was up and running in just 24 hours with Tommy senior navigation and obstacle avoidance capabilities. While Tommy Junior and Tommy senior share the same MAX DNA, Tommy Junior has since surpassed his father’s wits with new rules of behavior rapidly evolved for city driving.


 


2 – ThinkFree


ThinkFree is the compatible alternative to Microsoft Office. It includes ThinkFree Write (word processing), ThinkFree Calc (spreadsheet), and ThinkFree Show (presentation) applications that let you create, edit, and update your documents. The ThinkFree interface is designed to look, feel, and behaves like Microsoft Office, eliminating the learning curve. Because ThinkFree application use the same formats as Word, Excel, and PowerPoint, you can rest assured that your documents will look the same in ThinkFree as they do in Microsoft Office-no matter what editing features you are using. It can also save as PDF.


 


ThinkFree is written in Java, so it runs on Windows, Mac and Linux. There is a free online edition with 1 GB of storage, collaboration tools, publishing to blogs, web pages or ThinkFree Docs. I think it loads using Java Web Start? You can also host it on your own server, or run it as a desktop application.


 


1 – JPC


JPC is a pure Java emulation of an x86 PC with fully virtual peripherals. It runs anywhere you have a JVM, whether x86, RISC, mobile phone, set-top box, possibly even your refrigerator! All this, with the bulletproof security and stability of Java technology.


 


JPC creates a virtual computer upon which you can install your favorite operating system in a safe, flexible and powerful way. It aims to give you complete control over your favorite PC software’s execution environment, whatever your real hardware or operating system, and JPC’s multi-layered security makes it the safest solution for running the most dangerous software in quarantine – ideal for archiving viruses, hosting honey pots, and protecting your machine from malicious or unstable software.


It was hard to choose only ten application when there are so many cool looking scientific applications, 3D games, IDEs, languages that run on the JVM, etc. It’s incredible what people are doing with Java these days.


Also, there has been talk about aging mission critical real-time control systems transitioning to Java Real Time System (RTS) such as Nuclear Power Plants, Aircraft Control, Submarine Control, Factory Automation, Airport Aviation Flight Control, Energy and Power Systems Supply, Telecommunication Satellite and so forth. I saw a demonstration of the world’s fastest moving robot arm being controlled by a Java RTS application at JavaOne 2007. Very cool stuff.

Tomcat Today, GlassFish Tomorrow?

While there are indeed several advantages to using GlassFish vs. Tomcat, it’s probably useful to know that Sun is the original creator of Tomcat and that any application running today on Tomcat should run just fine (no modification whatsoever) on GlassFish.

Grizzly


Historically, if you wanted to get good HTTP performance from Tomcat you really needed to have a the Apache web server to sit in front of Tomcat which involved more setting up and extra administrative work. Since GlassFish v1 (May 2006), Grizzly is the HTTP frontend of the application server. It’s a 100% Java nio framework that provides the same performance as Apache only it’s written in Java and integrated straight into the application server. While using Apache or Sun Web Server in front of GlassFish is quite possible, it’s certainly no longer needed for performance reasons. Grizzly is also used for other protocols such as IIOP and now SIP (project Sailfin). Finally, Grizzly is the key technology for implementing Comet (aka Reverse Ajax, aka Ajax Push) which enables so very interesting push scenarios (from server to clients).


Full Java EE 5 support


Support for Java EE 5 (and soon Java EE 6) has always been a key priority for the GlassFish project. It delivered its first Java EE 5- certified implementation more than two years ago. This allowed developers to enjoy the much simplified EJB 3.0 specification, JAX-WS, and more goodness early on but it also provided dependency injection in the web tier (in servlet or JSF managed beans). Tomcat is not a full blown application server so while it may be enough for some developments, many companies find themselves maintaining a stack of frameworks and libraries on top of Tomcat when a GlassFish provides a JPA persistence engine (Toplink), a full web services stack (Metro), an application model (EJB3), and more, all out of the box. Java EE 6 profiles should help improve that situation for the industry as a whole.


Admin Tools


Administration and monitoring tools is what GlassFish users coming from Tomcat get as an immediate benefit. From web tools to command- line tools, GlassFish has an extensive set of features ranging from application (un)deployment, to JNDI resource creation, to all sorts of configuration details. All is JMX-based, exposed using MBeans (called AMX) and usable from JMX tools such as JConsole or the new VisualVM (specific plugin for GlassFish there). GlassFish also provides a fully- integrated monitoring feature called Call-Flow which reveals very accurately where time is being spent in the application before a response is sent. GlassFish also comes with a self-monitoring framework capable of implementing administrative rules such as the addition of a new node to a cluster if the average response time goes beyond a certain threshold.



Documentation


Technical information for GlassFish comes in various forms complementing one another quite well. The official documentation is extensive and complete (20+ books, from Developer’s Guide to Deployment Planning Guide). There’s also the Java EE tutorial, Enterprise Tech Tips, GlassFish user FAQs, blogs from engineers, forums and mailing lists.


Clustering


Full clustering is built right into GlassFish with no need to move to some other codebase or for-pay version of the product. In fact, you can even upgrade from a “developer” profile to a “cluster” profile. Clustering in GlassFish means the grouping technology (heartbeats, centralized admin), the load-balancing, but also the stateful data in- memory replication. Project Shoal is the GlassFish sub-project that does the heavy-lifting for most of these features. It uses JXTA under the covers which has the nice side-effect or requiring little to no configuration. GlassFish clustering make no assumption about the load- balancing technology used – it provides Web Server plugins but also works with hardware load-balancers. Such load-balancers do not need to know where the replicas are. Finally, Sun also offers a 99.999% solution with an in-memory distributed database (HADB). It has greater performance degradation, but probably unmatched availability.



Performance


Sun has literally worked for years on the performance of GlassFish – Grizzly, EJB container, Servlet container, Web Services, OpenMQ implementation, etc… The best result of this has been the SPECjAppServer world record published late last year and putting GlassFish in first place ahead of Weblogic and WebSphere (Tomcat isn’t a full app server and thus isn’t listed there, while JBoss has never published results). This is the first time one could claim that you no longer need to choose between open source and performance, you can have both. Performance is a strong priority for Sun.


Support from Sun


GlassFish is free and open source (dual CDDL + GPLv2 license), but Sun also has a business strategy to monetize GlassFish thru services. One such service is the subscription that covers access to patches and interim releases, access to support and escalation of bugs as well as indemnification. Sun also recently announced the GlassFish and MySQL unlimited offering (see http://www.sun.com/aboutsun/pr/2008-06/sunflash.20080627.1.xml) .


Tooling


While the NetBeans/GlassFish integration is very good, there is clearly no “NetBeans prerequisite” to use GlassFish. In fact Sun is the main developer of an open source plugin for Eclipse WTP to use GlassFish v2 and even v3. Both NetBeans and Eclipse users can get the plugin right from the IDE (for Eclipse, it’s a WTP plugin for Eclipse 3.3 or 3.4). There is also support for GlassFish in IntelliJ and Oracle has announced support in JDeveloper.


 


Tomcat, GlassFish v3


GlassFish has made a lot of efforts to appeal to developers. Its a single, small download of about 60MB, has auto-deploy capabilities, starts pretty fast for an application server with GlassFish v2 (probably the best full-blown application server startup time). To be fair to Tomcat or Jetty, they are still perceived by many as lighter- weight and faster to start. GlassFish v3 is all about being modular (based on OSGi), extensible and very developer friendly. The recently released TP2 (Tech Preview 2) starts in less than a second, starts/ stops containers and resources as needed and provides support for scripting technologies such as Rails, Groovy, PHP and more. There is also an Embedded mode for GlassFish which enables developers to use GlassFish via an API for testing or embeddability purposes. GlassFish v3 is scheduled to be aligned with Java EE 6 and released mid-2009. In the mean time there will be regular refreshes.


Is Hibernate the best choice?


Is Hibernate the best choice? Or is the technical marketing of other ORM vendors lacking?


Recently Jonathan Lehr posed a question on his blog: “Is Hibernate the best choice?“, and this lead me to ask the same question.


Although, I tend to use Hibernate as my first choice, it would be nice to see some head to head comparisons of Hibernate vs. TopLink (pros and cons), Hibernate vs. OpenJPA, Hibernate vs. Cayenne, etc. Searching around finds that many of the comparison are pretty old and not very detailed or compelling.


Having used other ORM frameworks, I found that when something goes wrong with Hibernate, you can usually google and find an answer, and there are many books on Hibernate. In my experience, the other frameworks seemed to be a less well-worn path and it is harder to find answers to even common problems. This is not to say that Hibernate is better, but that it is a lot more popular. In the end, I use Hibernate because my clients use it, if my clients switched to TopLink or OpenJPA, then I would use them as well.

So this begs the question, if Hibernate works for you, you just might have something else to do, like implementing a client solution that makes your client money, than to try several other ORM frameworks. How much time should someone spend learning a new ORM framework (new to them anyway)?


Don’t get this wrong, trying out new ORM frameworks is fine. If there is a large IT/developer organization, and you have a certain selection criteria like integrating with legacy databases, conformance to JPA specification, ability to hire new developers, easy of use, etc. then by all means having someone create a few prototypes and/or proofs of concepts and try out a few ORM frameworks is great. There is often good ROI in this type of testing. Perhaps share your findings with the rest of us.


However, it seems if you are a vendor of a JPA solution, you could start by pointing out how your product differs from Hibernate. Like it or not, Hibernate dominates the mind-share of developers. If you can’t prove your ORM frameworks has compelling reasons for switching, why should developers spend their time evaluating your product?


Now let me boil things down to brass tacks, it seems vendors of the ORMs should write white-papers, articles, blogs, and such to highlight the advantages of their ORM framework versus Hibernate. Logic dictates that if you have a product and there is a competing product that dominates the market that you might want to highlight what differentiates your product from the dominate one.


As a test, let’s go to different vendor sites and see if they have comparisons of their ORM framework vs. the 800 pound gorilla, Hibernate.


So first let’s go to Oracle TopLink website, you would expect since Hibernate has such a huge adoption rate in the industry that Oracle would want to point out why TopLink is better like a nice white-paper perhaps featured prominently on their TopLink site (see graph).


TopLink versus Hibernate


After hunting around a bit this entry appeared in the TopLink Essentials FAQ, Why should TopLink Essentials be used instead of JBoss(TM) Hibernate?


The two main points that seemed intriguing were as follows:


“Customers with any degree of complexity in the domain model or relational schemas, most notably where changing the schema is not an option, will benefit from the flexibility and proven nature of TopLink.”


NOTE: At times mapping Hibernate to legacy systems can be challenging. How is TopLink better at this? Are there articles or white-papers, etc. that attempt to prove that TopLink is better at legacy integration? (I find that many developers are not aware of all of the features that Hibernate provides for legacy mapping.)



“As the reference implementation of JPA TopLink offers the first certified implementation of this new standard. as well as providing some useful value-add functionality. Going forward this open source project will continue to innovate based on contributions from Oracle, Sun, and others.”


NOTE: This is compelling to me since I now use the JPA interface to Hibernate whenever I can.


Now I did not find the arguments in the FAQ particularly compelling or at all detailed. Sadly, you can find more compelling arguments in some of the TopLink public forums and random blogs. However, none so compelling that I feel the sudden need to switch.


Now on to the BEA site to look at dear KODO. I have always heard good things about KODO. Sadly, I found the BEA KODO site to be very out of date. It mentions a 2005 award for KODO as the lead news item. It also mentions that OpenJPA is in incubation, it has been out for a while. Even the FAQ, which did mention Hibernate, merely mentions that Hibernate is not EJB3 (seems it should say Hibernate is not JPA). This site really seems out of date and like the TopLink site mosty ignores the elephant in the room (see graph).


KODO vs. Hibernate


Well, let’s look at the Apache OpenJPA site, as KODO’s DNA may live at Apache long after Oracle decides on a single JPA solutions and likely leaves KODO to rot on the vine. Searching through the main site, FAQ, OpenJPA documentation, etc., I find no mention of Hibernate. Now this is an open source project so one would likely expect to see no marketing angle per se. But, you might expect that a project recognize that many would not be able to use this project without first justifying their pick against picking Hibernate (OpenJPA barely appears at all on job graphs). How many IT/development managers will feel comfortable with this choice without some explanation?


Now on to the next ORM framework site, Cayenne. No mention of Hibernate vs. Cayenne (but I know I have read articles on this). Seems like there might be some compelling ease-of-use arguments for Cayenne vs. Hibernate but they choose not to compare them. (Cayenne barely appears at all on job graphs)


Now back to Jonathan Lehr blog, Jonathan states that he feels TopLink and Cayenne are better choices than Hibernate and cites his reasons for these choices. There is a long discussion on the pros and cons of each in the comment section. I’d love to see more discussion, and I’d love to see some viable alternatives to Hibernate, but feel that no vendor or open source project does a real good job of pointing out the differences and possible limitations of Hibernate. If the vendors and project owners choose not to make their case, it makes it very difficult for the rank and file developers to make their case.


Perhaps one reason Hibernate is so dominate is because competing projects are so bad at technical marketing. Not one project I looked at mentions Hibernate on their front page. I could not find a decent comparison of features (to Hibernate’s) on any of the ORM sites.


Has anyone done a comparison of Hibernate and OpenJPA, TopLink Essentials, Cayenne that compares ease-of-use, caching, tool support, legacy integration, etc.? Perhaps such an internal report was used to decide which ORM tool to pick. If so, what were the results?


If you use TopLink, OpenJPA, Cayenne instead of Hibernate, why?


Were you hoping that JPA would level the playing field and there would be more competition?

Google Android Tutorial

Google has recently released the Android platform for developing mobile applications. The language used for developing Android programs is Java, but it is not Java Micro Edition.  No wireless application developer can ignore  Android. Google is the best known brand name, among the users of the web and Android comes from Google. 


I am presenting this hands-on tutorial, as a sequel to my j2me series. Adequate knowledge of core-java ,especially Event-handling, Swing and inner-classes is assumed. Though Android does not make use of Swing, it uses  similar ideas.


We can develop Android lessons and applications in Eclipse environment. Google have provided an Eclipse-plugin for Android. This is the popular method. Google has not given direct support to Netbeans. But some Netbeans users have developed a method for running Android in Netbeans . It is available at  http://undroid.nolimit.cz/. You can find more screenshots and guidance in http://eppleton.com/blog/.


We can develop Android lessons without using either Eclipse or Netbeans. The necessary command-line tools have been provided by Google. I found that using these command-line tools is easier than either Eclipse or Netbeans method. So, I am basing all the following lessons on these tools. I think, most readers will agree with my view, after they try this method as well as Eclipse method. The Android site at ‘code.google.com/android’ has already given step-by-step instructions about Android in Eclipse. You can also get more details with screen shots from  a wonderful website at www.tanguay.info/web/welcome.php titled ‘Edward’s Web Developer site’. He gives excellent guidance with plenty of screen shots 


The Android site lacks clarity about the command-line method. Hence, I think I am adding something useful by writing on the command-line method instead of simply repeating the material in Android site.
Let us start from the beginning. The first step is downloading the Android SDK (version m5-rc14, Feb-12, 2008). Android was released in November, 2007 . It has been revised in the Feb-2008 version.Some of the earlier examples may not work in the newer version.


I am working in Windows-2000 and so I downloaded the windows version. The supported platform in Windows is either Windows-XP or Vista.(Mac OS 10 & Ubuntu Linux are the other platforms mentioned). However, it works well in my Win-2000. It is advisable to have at least 512MB memory. The android SDK is a zip file. I unzipped it to C:\unzipped\android and later, I copied that folder to D:\android. If you want, you can simply copy it to another drive like G:\android also. In the following lessons D:\android is used.


If you want to develop using Eclipse, you must have installed either Eclipse3.2 or Eclipse3.3(Europa). I have tested with Eclipse3.2. No problem.It works. But, we require ADT  (ie) Android Development Tools plugin for Eclipse, if you are using Eclipse.You can get this plugin from http://code.google.com/android/adt_download. You have to be careful about the ADT version number.It is ADT-0.3.3.



As my present focus is on command-line method, let me begin straight away and give a simple demo.The procedure given here is common for all our experiments and so I will not be repeating it in each demo. So, please note it down carefully.


Demo 1 – TextBox


In my first demo, I will have a customary button and textbox ( called EditField in Android). When I click the button, I want the message “SUCCESS!” to be displayed in textbox. Just as an exercise, I am using two buttons and two textboxes.



The first step is to start the Emulator


cd to d:\android\tools

d:\android\tools>emulator


It will take a long time to get started. Do not be in a hurry. Wait till it gets fully started. And do not  close that window carelessly by mistake. In that case, you will have to start it again and wait for a long time again. Finally, we get the emulator screen
 


The second step is to give the following command, from another command window.


d:\android\tools>

activityCreator –out  demo                                   mypack.mydemos.demo


This means that my project is ‘demo’ and my package is ‘mypack.mydemos’. A number of folders are created automatically by this command:



  • tools\demo\src
  • tools\demo\bin
  • tools\demo\res.  

We need to note  the src and res folders carefully. We will place the java source file in src folder and main.xml file in res\layout, overwriting any files that are generated automatically. For the moment, we can think of the res\layout folder as the one which decides the gui design. As in asp.net, flex etc, the gui details are specified in xml file. But how shall we write the XML file? by hand? Not too difficult .But….luckily, there is an open-source gui designer named ‘DroidDraw’ available in http://www.droiddraw.org/ .It is a nice tool and if you like it, you can send your appreciation to [email protected]. He has given a simple tutorial too, on how to use this gui tool.


I downloaded this software from the above site. I unzipped it. ( any folder). When we click on the icon, we get the screen as given below.


Droid DrawDroid Draw


 


Drawing Canvas AreaDrawing Canvas Area



Toolbox &amp; Blank AreaToolbox & Blank Area 


Thus we get a window, showing the drawing canvas on leftside and toolbox and a blank area in the rightside. ( for printing purpose, I have split them into two screens) as above.



From the toolbox, we learn that we are having controls like button,check,radio,spinner,edittext(textbox) and  textview (label) etc. There is also a combo  to choose  layout, in the canvas screen.  I am choosing ‘absolute layout’. I simply drag and drop a button and an editview on the canvas.(Drag and drop, do not click and drop! It won’t work).


You will notice a number of tabs in toolbox. Select ‘properties’ tab.. After clicking the button on the canvas, give the id property of button as @id/button1. Similarly, for editview as @id/text1. Also, button2 and text2 After this, just click the ‘generate’ button at the bottom of  the blank window. We get the following XML file(main.xml) automatically generated.





  1. <?xml version=“1.0” encoding=“utf-8”?>  

  2. <RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”  

  3.     android:layout_width=“fill_parent” android:layout_height=“wrap_content”  

  4.     android:padding=“10px”>  

  5.     <EditText android:id=“@+id/text1” android:layout_width=“fill_parent”  

  6.         android:layout_height=“wrap_content” />  

  7.     <Button android:id=“@+id/button1” android:layout_width=“wrap_content”  

  8.         android:layout_height=“wrap_content” android:layout_below=“@id/text1”  

  9.         android:layout_alignParentRight=“true” android:layout_marginLeft=“10px”  

  10.         android:text=“click” />  

  11.     <EditText android:id=“@+id/text2” android:layout_width=“fill_parent”  

  12.         android:layout_height=“wrap_content” android:layout_below=“@id/button1” />  

  13.     <Button android:id=“@+id/button2” android:layout_width=“wrap_content”  

  14.         android:layout_height=“wrap_content” android:layout_below=“@id/text2”  

  15.         android:layout_alignParentRight=“true” android:layout_marginLeft=“10px”  

  16.         android:text=“click” />  

  17. </RelativeLayout>  

We can now create our java source file. The code refers to main.xml for id of the controls.
(d:\android\mydemos\ex1\demo.java).This is our work folder.





  1. package mypack.mydemos;   

  2.   

  3.   

  4. import android.app.Activity;   

  5. import android.os.Bundle;   

  6. import android.view.View;   

  7. import android.widget.*;   

  8.   

  9.   

  10. public class demo extends Activity     

  11. {   

  12.   

  13. Button     button1,button2;   

  14. EditText   text1,text2;   

  15.   

  16.     @Override  

  17.   

  18.     public void onCreate(Bundle icicle)   

  19.     {   

  20.         super.onCreate(icicle);   

  21.         setContentView(R.layout.main);   

  22.     text1=  (EditText) findViewById(R.id.text1);   

  23.     button1 = (Button) findViewById(R.id.button1);   

  24.   

  25.     text2=  (EditText) findViewById(R.id.text2);   

  26.     button2 = (Button) findViewById(R.id.button2);   

  27.     button1.setOnClickListener(new clicker());   

  28.     button2.setOnClickListener(new clicker());   

  29.    }   

  30.   

  31.  //———————————–   

  32.   

  33.  class  clicker implements Button.OnClickListener   

  34.   {                  

  35.   public void onClick(View v)   

  36.      {   

  37.      if(v==button1){text1.setText(“welcome”); }   

  38.      if(v==button2){text2.setText(“hello”);   }        

  39.      }   

  40.   

  41.   }   

  42.   

  43. }  

The Android documentation and sample programs use anonymous inner class. I think it is quite unnecessary and is very tedious to follow. Instead, I have used user-defined ‘clicker’. This makes the code cleaner and more readable. This is just like any Swing program. In Android Terminology, an Activity is like a frame in swing (a screen). Just like ActionListener, here also we have, OnClickListener. I am not going into detailed theory now. I just  want to show how to develop and run a program first. Theory will follow later.


We have to copy this file(demo.java) to D:\android\tools\demo\src\mypack\mydemos


Go to d:\android\tools\demo

Give path= c:\winNT\system32;c:\jdk1.5\bin;e:\ant1.6\bin

(carefully note that this will not work with jdk1.4.2. It requires jdk1.5).


Secondly, how about the reference to Ant? Ant is a famous build tool from Apache Software foundation. Android requires the latest version of Ant for Windows(ie) Ant1.6. Do I have to know how to write the Ant’s build.xml file? NO. It is automatically created by the command.


So, I downloaded ant1.6 from the Apache website. It is a compact zip file. I have unzipped it and placed it as E:\ant1.6). Now use the command ‘ant’


d:\android\tools\demo>ant

We will get a series of messages. If we had done the previous steps correctly, we will get the message ‘BUILD SUCCESSFUL”.  Otherwise, we will get error messages, with line numbers where the errors occurred. We can correct them and build again.


The build process would have created a zip file named ‘demo.apk’ in demo\bin folder. All that remains now is to run the program in the emulator. As you remember, we have already started the emulator and it is running.


Now copy d:\android\tools\demo\bin\demo.apk  to d:\android\tools. After copying, give the command as:


…\tools>adb   install    demo.apk

After giving this command. go to the emulator window. You will find a checkpattern displayed for a while. Then an additional button appears in the screen with caption ‘demo’. Our program has been installed. We can test it by clicking on this ‘demo’button.


 



You can execute the program ‘demo’ now. Two textboxes and two buttons will appear. Click on button1. ‘welcome’ will appear in text1. Click on button2.’how are you?’ will appear in text2. The result is shown  below.



That completes our first  demo in  android.


We will be following exactly same procedure for all our demos. We will hereafter, see xml file and java files only, for the various demos. After a few more demos, it will be enough if I give the imports, declaration, definition and event handler.


The Android SDK comes with a number of sample applications. Within the APIDemos folder, we have a folder named ‘Views‘. I read it as ‘GUI’. It deals with layouts and controls and animations etc. There are a lot of demos. It may be confusing at first. Though, we may like to modify and simplify the code later, it is instructive to try each one of the sample programs by clicking on ‘apidemos’ button in the emulator screen and getting familiarity . I will list and give a brief comment on these, later.


 


Demo 2 – Spinner


As usual, the standard widgets are label(textview), textbox(edittext), combo(spinner), check, radio, ticker etc. I will now give a  demo for spinner. I have provided a spinner, button and a text to display the selected item in edittext.


We can design our layout as before using DroidDraw and get the following main.xml.


(obtained by using DroidDraw).





  1. <?xml version=“1.0” encoding=“utf-8”?>  

  2. <AbsoluteLayout android:id=“@+id/widget0”    

  3.     android:layout_width=“fill_parent”    

  4.      android:layout_height=“fill_parent”    

  5.       xmlns:android=“http://schemas.android.com/ apk/res/android”>                                               

  6. <Spinner  android:id=“@+id/spinner1” android:layout_width=“wrap_content” android:layout_height=“wrap_content” android:layout_x=“70px” android:layout_y=“42px”>                                               

  7. </Spinner>  

  8. <Button android:id=“@+id/button1” android:layout_width=“wrap_content” android:layout_height=“wrap_content” android:text=“confirm” android:layout_x=“70px” android:layout_y=“112px”>                                           </Button>                                      

  9. <EditText android:id=“@+id/text1” android:layout_width=“wrap_content” android:layout_height=“wrap_content” android:text=“EditText” android:textSize=“18sp” android:layout_x=“70px” android:layout_y=“182px”>  

  10. </EditText>  

  11. </AbsoluteLayout>  

The corresponding java source file is given below.





  1. package  mypack.mydemos;         

  2.   

  3. import android.app.Activity;                     

  4. import android.os.Bundle;                        

  5. import android.widget.*;      

  6. import android.view.View;   

  7.   

  8. public class  demo extends Activity              

  9. {                                                       

  10.         Spinner   spinner1;  

  11.         Button    button1;             

  12.         EditText   text1;    

  13.   

  14.       @Override                                                  

  15.       protected void onCreate(Bundle icicle)     

  16.   

  17.       {         

  18.                 super.onCreate(icicle);                             

  19.                 setTheme(android.R.style.Theme_Dark);  

  20.                 setContentView(R.layout.main);     

  21.     spinner1 = (Spinner)    

  22.     findViewById  (R.id.spinner1);     

  23.     button1    = (Button);  

  24.     findViewById (R.id.button1);                                                 

  25.     text1      = (EditText)    

  26.     findViewById  (R.id.text1);          

  27.     ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, array);           

  28.     adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_ item);                      

  29.     spinner1.setAdapter(adapter);           

  30.     button1.setOnClickListener(  new clicker());      

  31.    }            

  32.   

  33.          private static final String[] array = {        “sunday”“monday”“tuesday”“wednesday”,  

  34.                          “thursday”“friday”“saturday” };     

  35.   

  36. class  clicker implements  Button.OnClickListener   

  37.   

  38. {   

  39.     public   void  onClick(View   v)  

  40.               {           

  41.            String       s = (String) spinner1.getSelectedItem();   

  42.              text1.setText(s);                                  

  43.     }                                            

  44.   

  45. }      

  46.   

  47.   

  48. }  

As before place demo.java in d:\android\tools\demo\src\mypack\mydemos. Place main.xml in d:\android\tools\demo\res\layout


Build using ant. Deploy demo.apk to the emulator exactly as in previous demo. The original demo gets overwritten. But, our work folder , where we have our xml and java files is d:\android\mydemos\ex1.They  are intact. So, no problem..The current java and xml files are in d:\android\mydemos\ex2.


When we click on the spinner, we get the items displayed as drop-down. We select an item and confirm. The selected item appears in text1. I am not going to explain the code. It is simple enough, if we remember our core java.



Demo 3 – Ticker


The third demo is a ‘ticker’ having a textbox for entering the ticker’s text, a ticker(timer) , two labels(editview) one for status and the other for diplaying the sliding message.





  1. <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android   

  2.    android:layout_width=“fill_parent”       

  3.    android:layout_height=“fill_parent”       

  4.    android:orientation=“vertical”>                                                                              

  5. <EditText android:id=“@+id/text1”           

  6.    android:layout_width=“fill_parent”           

  7.    android:layout_height=“wrap_content” />                                                                             

  8. <Ticker android:id=“@+id/ticker1”           

  9. android:layout_width=“fill_parent”           

  10. android:layout_height=“wrap_content”    

  11. android:layout_marginTop=“20dip” />                                                                      

  12. <TextView android:id=“@+id/label1”               

  13.   android:layout_width=“wrap_content”               

  14.   android:layout_height=“fill_parent” />                                                                       

  15.  </Ticker>  

  16. <TextView android:id=“@+id/label2”           

  17.   android:layout_width=“fill_parent”           

  18.   android:layout_height=“wrap_content”           

  19.    android:layout_marginTop=“20dip”  />                                                             

  20. </LinearLayout>  

 LinearLayout with vertical orientation is like FlowLayout but in a vertical direction.






  1. package mypack.mydemos;   

  2.   

  3. import android.app.Activity;   

  4. import android.os.Handler;   

  5. import android.os.Bundle;   

  6. import android.view.View;   

  7. import android.view.View.OnClickListener;   

  8. import android.widget.*;   

  9. import java.util.Map;   

  10.   

  11. public class demo extends Activity   

  12.   

  13. implements Ticker.TickerListener {   

  14.     Ticker ticker1;   

  15.     TextView label1, label2;   

  16.     EditText text1;   

  17.   

  18.     @Override  

  19.     protected void onCreate(Bundle icicle) {   

  20.         super.onCreate(icicle);   

  21.         setContentView(R.layout.main);   

  22.         ticker1 = (Ticker) findViewById(R.id.ticker1);   

  23.         label1 = (TextView) findViewById(R.id.label1);   

  24.         label2 = (TextView) findViewById(R.id.label2);   

  25.         text1 = (EditText) findViewById(R.id.text1);   

  26.         ticker1.setTickerListener(this);   

  27.         text1.setOnClickListener(new clicker());   

  28.     }   

  29.   

  30.     class clicker implements EditText.OnClickListener {   

  31.         public void onClick(View v) {   

  32.   

  33.             label1.setText(text1.getText());   

  34.             ticker1.startTicker();   

  35.             label2.setText(“Ticking…”);   

  36.         }   

  37.     }   

  38.   

  39.     public void onTickerFinished(Ticker view) {   

  40.         label2.setText(“Done!”);   

  41.     }   

  42.   

  43. }  

 


Demo 4 – Checkbox 


Copy this to tools\demo\res\layout\


 





  1. <?xml version=“1.0” encoding=“utf-8”?>  

  2. <AbsoluteLayout android:id=“@+id/widget1”  

  3.     android:layout_width=“fill_parent” android:layout_height=“fill_parent”  

  4.     xmlns:android=“http://schemas.android.com/ apk/res/android”>  

  5.     <CheckBox android:id=“@+id/check1”  

  6.         android:layout_width=“wrap_content”  

  7.         android:layout_height=“wrap_content” android:text=“java”  

  8.         android:layout_x=“50px” android:layout_y=“22px”>  

  9.     </CheckBox>  

  10.   

  11.     <CheckBox android:id=“@+id/check2”  

  12.         android:layout_width=“wrap_content”  

  13.         android:layout_height=“wrap_content” android:text=“C#”  

  14.         android:layout_x=“50px” android:layout_y=“72px”>  

  15.     </CheckBox>  

  16.   

  17.     <Button android:id=“@+id/button1”  

  18.         android:layout_width=“wrap_content”  

  19.         android:layout_height=“wrap_content” android:text=“Confirm”  

  20.         android:layout_x=“60px” android:layout_y=“122px”>  

  21.     </Button>  

  22.   

  23.     <EditText android:id=“@+id/text1”  

  24.         android:layout_width=“wrap_content”  

  25.         android:layout_height=“wrap_content” android:text=“EditText”  

  26.         android:textSize=“18sp” android:layout_x=“60px”  

  27.         android:layout_y=“202px”>  

  28.     </EditText>  

  29. </AbsoluteLayout>  

 


To be copied to tools\demo\mypack\mydemos





  1. package mypack.mydemos;   

  2.   

  3. import android.app.Activity;   

  4. import android.os.Bundle;   

  5. import android.view.View;   

  6. import android.widget.*;   

  7.   

  8. public class demo extends Activity   

  9.   

  10. {   

  11.   

  12.     Button button1;   

  13.     CheckBox check1, check2;   

  14.     EditText text1;   

  15.   

  16.     @Override  

  17.     public void onCreate(Bundle icicle)   

  18.   

  19.     {   

  20.         super.onCreate(icicle);   

  21.         setContentView(R.layout.main);   

  22.         text1 = (EditText) this.findViewById(R.id.text1);   

  23.         check1 = (CheckBox) findViewById(R.id.check1);   

  24.         check2 = (CheckBox) findViewById(R.id.check2);   

  25.   

  26.         button1 = (Button) findViewById(R.id.button1);   

  27.         button1.setOnClickListener(new clicker());   

  28.   

  29.     }   

  30.   

  31.     class clicker implements Button.OnClickListener   

  32.   

  33.     {   

  34.         public void onClick(View v)   

  35.   

  36.         {   

  37.   

  38.             String r = “”;   

  39.             if (check1.isChecked())   

  40.             {   

  41.                 r = r + “java” + “\n”;   

  42.             }   

  43.             if (check2.isChecked())   

  44.             {   

  45.                 r = r + “c#”;   

  46.             }   

  47.             text1.setText(r);   

  48.         }   

  49.   

  50.     }   

  51.   

  52. }  

 


This is just the usual Java code and needs very little explanation. The only difference is the way , the controls are defined ( through res\layout\xml file).


 


Demo 5 – RadioButtons


The next standard control is the RadioButton, within a RadioGroup.


To be placed in tools\demo\res\layout





  1. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  

  2.     android:orientation=“vertical” android:layout_width=“fill_parent”  

  3.     android:layout_height=“wrap_content”>  

  4.     <RadioGroup android:id=“@+id/group1” android:layout_width=“fill_parent”  

  5.         android:layout_height=“wrap_content” android:orientation=“vertical”>  

  6.         <RadioButton android:id=“@+id/radio1” android:text=“madras”  

  7.             android:layout_width=“wrap_content” android:layout_height=“wrap_content” />  

  8.         <RadioButton android:id=“@+id/radio2” android:text=“bombay”  

  9.             android:layout_width=“wrap_content” android:layout_height=“wrap_content” />  

  10.     </RadioGroup>  

  11.     <Button android:id=“@+id/button1” android:layout_width=“wrap_content”  

  12.         android:layout_height=“wrap_content” android:text=“Button” />  

  13.     <TextView android:id=“@+id/label1” android:layout_width=“wrap_content”  

  14.         android:layout_height=“wrap_content” android:text=“where” />  

  15.     <EditText android:id=“@+id/text1” android:layout_width=“wrap_content”  

  16.         android:layout_height=“wrap_content” android:text=“” android:textSize=“18sp”  

  17.         android:layout_x=“70px” android:layout_y=“182px” />  

  18. </LinearLayout>  

The following Java code should be placed in tools\demo\src\mypack\mydemo





  1. package mypack.mydemos;   

  2.   

  3. import android.app.Activity;   

  4.   

  5. import android.os.Bundle;   

  6.   

  7. import android.view.View;   

  8.   

  9. import android.widget.*;   

  10.   

  11. public class demo extends Activity   

  12.   

  13. {   

  14.   

  15.     TextView label1;   

  16.   

  17.     RadioGroup group1;   

  18.   

  19.     RadioButton radio1, radio2;   

  20.   

  21.     Button button1;   

  22.   

  23.     EditText text1;   

  24.   

  25.     @Override  

  26.     protected void onCreate(Bundle icicle)   

  27.   

  28.     {   

  29.   

  30.         super.onCreate(icicle);   

  31.   

  32.         setContentView(R.layout.main);   

  33.   

  34.         group1 = (RadioGroup)   

  35.   

  36.         findViewById(R.id.group1);   

  37.   

  38.         radio1 = (RadioButton)   

  39.   

  40.         findViewById(R.id.radio1);   

  41.   

  42.         radio2 = (RadioButton)   

  43.   

  44.         findViewById(R.id.radio2);   

  45.   

  46.         button1 = (Button) findViewById(R.id.button1);   

  47.   

  48.         text1 = (EditText) findViewById(R.id.text1);   

  49.   

  50.         text1.setText(“radio”);   

  51.   

  52.         label1 = (TextView) findViewById(R.id.label1);   

  53.   

  54.         label1.setText(“where?”);   

  55.   

  56.         button1.setOnClickListener(new clicker());   

  57.   

  58.     }   

  59.   

  60.     // …inner class —follows ->   

  61.   

  62.     class clicker implements Button.OnClickListener   

  63.   

  64.     {   

  65.   

  66.         public void onClick(View v)   

  67.   

  68.         {   

  69.   

  70.             if (v == button1)   

  71.   

  72.             {   

  73.   

  74.                 if (radio1.isChecked())   

  75.   

  76.                 {   

  77.                     text1.setText(“madras”);   

  78.                 }   

  79.   

  80.                 if (radio2.isChecked())   

  81.   

  82.                 {   

  83.                     text1.setText(“bombay”);   

  84.                 }   

  85.   

  86.             }   

  87.   

  88.         }   

  89.   

  90.     }   

  91.   

  92.     // —-inner class ends here —   

  93.   

  94. }  

 


You would have observed that I am naming all my java files as ‘demo.java’. May be confusing at first but I am doing so with a purpose. First of all, the emulator screen gets cluttered with too many buttons if we go on adding my examples. What I have done is :


I have created a folder as d:\android\mydemos.


In mydemos folder, I have created subfolders such as (ex1,ex2 etc). But, within each folder, I have demo.java & main.xml.


This way, we can easily test each of our demos  by uniform procedure. In my system, I had the problem of insufficient memory. And, by the above step, I was able to test all my programs by the same name.


Here is an important tip however, if you choose to name the source files and xml files differently and want to reduce the clutter.


Demo 6 – Gallery 


Interestingly, there is a ready-made control in the toolbox, named ‘gallery’. Let us now learn to use this control, though the syntax is a bit difficult. This time, we will need demo.java, main.xml and also another folder in tools\demo\res\drawable. This special folder is to be created by us. You can read ‘img’ instead of ‘drawable’. So, we place all the image files to be displayed in the gallery, in this folder.


 


Let us as usual create the xml file by using DroidDraw as follows.


 





  1. <?xml version=“1.0” encoding=“utf-8”?>  

  2. <Gallery xmlns:android=“http://schemas.android.com/apk/res/android”  

  3.     android:id=“@+id/gallery” android:layout_width=“fill_parent”  

  4.     android:layout_height=“fill_parent” android:layout_alignParentBottom=“true”  

  5.     android:layout_alignParentLeft=“true” android:gravity=“center_vertical”  

  6.     android:spacing=“5” />  

 


The following class is to be placed in tools\demo\mypack\mydemos





  1. package mypack.mydemos;   

  2.   

  3. import android.app.Activity;   

  4. import android.content.Context;   

  5. import android.os.Bundle;   

  6. import android.view.View;   

  7. import android.view.ViewGroup;   

  8. import android.widget.*;   

  9. import android.widget.AdapterView.OnItemClickListener;   

  10.   

  11. public class example extends Activity   

  12.   

  13. {   

  14.   

  15.     @Override  

  16.     public void onCreate(Bundle icicle) {   

  17.   

  18.         super.onCreate(icicle);   

  19.         setContentView(R.layout.main);   

  20.         Gallery gallery = (Gallery)   

  21.         findViewById(R.id.gallery);   

  22.         gallery.setAdapter(new ImageAdapter(this));   

  23.         gallery.setOnItemClickListener(new OnItemClickListener()   

  24.         {   

  25.   

  26.             public void onItemClick(AdapterView parent,   

  27.             View v,   

  28.             int position,   

  29.             long id)   

  30.   

  31.             {   

  32.   

  33.                 Toast.makeText(example.this“” + position,   

  34.                 Toast.LENGTH_SHORT).show();   

  35.             }   

  36.   

  37.         });   

  38.   

  39.     }   

  40.   

  41.     public class ImageAdapter extends BaseAdapter   

  42.     {   

  43.   

  44.         public ImageAdapter(Context c)   

  45.         {   

  46.             mContext = c;   

  47.         }   

  48.   

  49.         public int getCount()   

  50.         {   

  51.             return mImageIds.length;   

  52.         }   

  53.   

  54.         public Object getItem(int position)   

  55.         {   

  56.             return position;   

  57.         }   

  58.   

  59.         public long getItemId(int position)   

  60.         {   

  61.             return position;   

  62.         }   

  63.   

  64.         public View getView(int position, View   

  65.         convertView, ViewGroup parent)   

  66.         {   

  67.             ImageView i = new ImageView(mContext);   

  68.             i.setImageResource(mImageIds[position]);   

  69.             i.setScaleType(ImageView.ScaleType.FIT_XY);   

  70.             i.setLayoutParams(new Gallery.LayoutParams(160200));   

  71.             return i;   

  72.         }   

  73.   

  74.         public float getAlpha(boolean focused, int offset)   

  75.         {   

  76.             return Math.max(01.0f – (0.2f * Math.abs(offset)));   

  77.         }   

  78.   

  79.         public float getScale(boolean focused, int offset)   

  80.         {   

  81.             return Math.max(01.0f – (0.2f *   

  82.             Math.abs(offset)));   

  83.         }   

  84.         private Context mContext;   

  85.         private Integer[] mImageIds = {   

  86.         R.drawable.cindy,   

  87.         R.drawable.clinton,   

  88.         R.drawable.ford,   

  89.         R.drawable.cybil,   

  90.         R.drawable.demi,   

  91.         R.drawable.colin,   

  92.         R.drawable.david,   

  93.         R.drawable.drew   

  94.         };   

  95.   

  96.     }   

  97.   

  98. }  

How to uninstall an application from the emulator?



  • Make sure your emulator is running
  • Open a dos box in the android/tools folder  d:\android\tools>adb shell 
  • You will get the shell prompt
     #cd /data/app
     #ls
     (It will list all the *.apk installed in your emulator)
    # rm  example.apk
    ( if you want to remove ‘example’)
    #exit
  • You will see the application getting removed from the emulator at the same moment

 


That completes the first part of my introductory tutorial on Android SDK.


 

Pathway from ACEGI to Spring Security 2.0

Formerly called ACEGI Security for Spring, the re-branded Spring Security 2.0 has delivered on its promises of making it simpler to use and improving developer productivity. Already considered as the Java platform’s most widely used enterprise security framework with over 250,000 downloads from SourceForge, Spring Security 2.0 provides a host of new features.

This article outlines how to convert your existing ACEGI based Spring application to use Spring Security 2.0.


What is Spring Security 2.0


Spring Security 2.0 has recently been released as a replacement to ACEGI and it provides a host of new security features:



  • Substantially simplified configuration.

  • OpenID integration, single sign on standard.

  • Windows NTLM support, single sign on against Windows corporate networks.

  • Support for JSR 250 (“EJB 3”) security annotations.

  • AspectJ pointcut expression language support.

  • Comprehensive support for RESTful web request authorization.

  • Long-requested support for groups, hierarchical roles and a user management API.

  • An improved, database-backed “remember me” implementation.

  • New support for web state and flow transition authorization through the Spring Web Flow 2.0 release.

  • Enhanced WSS (formerly WS-Security) support through the Spring Web Services 1.5 release.

  • A whole lot more…

Goal


Currently I work on a Spring web application that uses ACEGI to control access to the secure resources. Users are stored in a database and as such we have configured ACEGI to use a JDBC based UserDetails Service. Likewise, all of our web resources are stored in the database and ACEGI is configure to use a custom AbstractFilterInvocationDefinitionSource to check authorization details for each request.
With the release of Spring Security 2.0 I would like to see if I can replace ACEGI and keep the current ability to use the database as our source of authentication and authorization instead of the XML configuration files (as most examples demonstrate).


Here are the steps that I took…


Steps



  1. The first (and trickiest) step was to download the new Spring Security 2.0 Framework and make sure that the jar files are deployed to the correct location. (/WEB-INF/lib/)
    There are 22 jar files that come with the Spring Security 2.0 download. I did not need to use all of them (especially not the *sources packages). For this exercise I only had to include:


    • spring-security-acl-2.0.0.jar


    • spring-security-core-2.0.0.jar


    • spring-security-core-tiger-2.0.0.jar


    • spring-security-taglibs-2.0.0.jar

  2. Configure a DelegatingFilterProxy in the web.xml file.




    1. <filter>  

    2.     <filter-name>springSecurityFilterChain</filter-name>  

    3.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  

    4. </filter>  

    5. <filter-mapping>  

    6.     <filter-name>springSecurityFilterChain</filter-name>  

    7.     <url-pattern>/*</url-pattern>  

    8. </filter-mapping>  

  3. Configuration of Spring Security 2.0 is far more concise than ACEGI, so instead of changing my current ACEGI based configuration file, I found it easier to start from a empty file. If you do want to change your existing configuration file, I am sure that you will be deleting more lines than adding.

    The first part of the configuration is to specifiy the details for the secure resource filter, this is to allow secure resources to be read from the database and not from the actual configuration file. This is an example of what you will see in most of the examples:




    1. <http auto-config=“true” access-denied-page=“/403.jsp”>  

    2.     <intercept-url pattern=“/index.jsp” access=“ROLE_ADMINISTRATOR,ROLE_USER”/>  

    3.     <intercept-url pattern=“/securePage.jsp” access=“ROLE_ADMINISTRATOR”/>  

    4.     <intercept-url pattern=“/**” access=“ROLE_ANONYMOUS” />  

    5. </http>  
    Replace this with:




    1. <authentication-manager alias=“authenticationManager”/>  

    2.       

    3. <beans:bean id=“accessDecisionManager” class=“org.springframework.security.vote.AffirmativeBased”>  

    4.     <beans:property name=“allowIfAllAbstainDecisions” value=“false”/>  

    5.     <beans:property name=“decisionVoters”>  

    6.         <beans:list>  

    7.             <beans:bean class=“org.springframework.security.vote.RoleVoter”/>  

    8.             <beans:bean class=“org.springframework.security.vote.AuthenticatedVoter”/>  

    9.         </beans:list>  

    10.     </beans:property>  

    11. </beans:bean>  

    12.   

    13. <beans:bean id=“filterInvocationInterceptor” class=“org.springframework.security.intercept.web.FilterSecurityInterceptor”>  

    14. <beans:property name=“authenticationManager” ref=“authenticationManager”/>  

    15.     <beans:property name=“accessDecisionManager” ref=“accessDecisionManager”/>  

    16.     <beans:property name=“objectDefinitionSource” ref=“secureResourceFilter” />  

    17. </beans:bean>  

    18.       

    19. <beans:bean id=“secureResourceFilter” class=“org.security.SecureFilter.MySecureResourceFilter” />  

    20.   

    21. <http auto-config=“true” access-denied-page=“/403.jsp”>  

    22.     <concurrent-session-control max-sessions=“1” exception-if-maximum-exceeded=“true” />  

    23.     <form-login login-page=“/login.jsp” authentication-failure-url=“/login.jsp” default-target-url=“/index.jsp” />  

    24.     <logout logout-success-url=“/login.jsp”/>  

    25.  </http>  

    The main part of this piece of configuration is the secureResourceFilter, this is a class that implementsFilterInvocationDefinitionSource and is called when Spring Security needs to check the Authorities for a requested page.
    Here is the code for MySecureResourceFilter:




    1. package org.security.SecureFilter;  

    2.   

    3. import java.util.Collection;  

    4. import java.util.List;  

    5.   

    6. import org.springframework.security.ConfigAttributeDefinition;  

    7. import org.springframework.security.ConfigAttributeEditor;  

    8. import org.springframework.security.intercept.web.FilterInvocation;  

    9. import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;  

    10.   

    11.   

    12. public class MySecureResourceFilter implements FilterInvocationDefinitionSource {  

    13.   

    14.     public ConfigAttributeDefinition getAttributes(Object filter) throws IllegalArgumentException {  

    15.           

    16.         FilterInvocation filterInvocation = (FilterInvocation) filter;  

    17.           

    18.         String url = filterInvocation.getRequestUrl();  

    19.           

    20.         // create a resource object that represents this Url object  

    21.         Resource resource = new Resource(url);  

    22.           

    23.         if (resource == nullreturn null;  

    24.         else{  

    25.             ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();  

    26.             // get the Roles that can access this Url  

    27.             List<Role> roles = resource.getRoles();  

    28.             StringBuffer rolesList = new StringBuffer();  

    29.             for (Role role : roles){  

    30.                 rolesList.append(role.getName());  

    31.                 rolesList.append(“,”);  

    32.             }  

    33.             // don’t want to end with a “,” so remove the last “,”  

    34.             if (rolesList.length() > 0)  

    35.                 rolesList.replace(rolesList.length()-1, rolesList.length()+1“”);  

    36.             configAttrEditor.setAsText(rolesList.toString());  

    37.             return (ConfigAttributeDefinition) configAttrEditor.getValue();  

    38.         }         

    39.     }  

    40.   

    41.     public Collection getConfigAttributeDefinitions() {  

    42.         return null;  

    43.     }  

    44.   

    45.     public boolean supports(Class arg0) {  

    46.         return true;  

    47.     }  

    48.   

    49. }  
    This getAttributes() method above essentially returns the name of Authorities (which I call Roles) that are allowed access to the current Url.

  4. OK, so now we have setup the database based resources and now the next step is to get Spring Security to read the user details from the database. The examples that come with Spring Security 2.0 shows you how to keep a list of users and authorities in the configuration file like this:




    1. <authentication-provider>  

    2.     <user-service>  

    3.     <user name=“rod” password=“password” authorities=“ROLE_SUPERVISOR, ROLE_USER” />  

    4.     <user name=“dianne” password=“password” authorities=“ROLE_USER,ROLE_TELLER” />  

    5.     <user name=“scott” password=“password” authorities=“ROLE_USER” />  

    6.     <user name=“peter” password=“password” authorities=“ROLE_USER” />  

    7.     </user-service>  

    8. </authentication-provider>  
    You could replace these examples with this configuration so that you can read the user details straight from the database like this:




    1. <authentication-provider>  

    2.     <jdbc-user-service data-source-ref=“dataSource” />  

    3. </authentication-provider>  
    While this is a very fast and easy way to configure database based security it does mean that you have to conform to a default databases schema. By default, the <jdbc-user-service> requires the following tables: user, authorities, groups, group_members and group_authorities.
    In my case this was not going to work as my security schema it not the same as what the <jdbc-user-service>requires, so I was forced to change the <authentication-provider>:




    1. <authentication-provider>  

    2.     <jdbc-user-service data-source-ref=“dataSource”  

    3.     users-by-username-query=“SELECT U.username, U.password, U.accountEnabled AS ‘enabled’ FROM User U where U.username=?”  

    4.     authorities-by-username-query=“SELECT U.username, R.name as ‘authority’ FROM User U JOIN Authority A ON u.id = A.userId JOIN Role R ON R.id = A.roleId WHERE U.username=?”/>  

    5. </authentication-provider>  
    By adding the users-by-username-query and authorities-by-username-query properties you are able to override the default SQL statements with your own. As in ACEGI security you must make sure that the columns that your SQL statement returns is the same as what Spring Security expects. There is a another property group-authorities-by-username-query which I am not using and have therefore left it out of this example, but it works in exactly the same manner as the other two SQL statements.

    This feature of the <jdbc-user-service> has only been included in the past month or so and was not available in the pre-release versions of Spring Security. Luckily it has been added as it does make life a lot easier. You can read about this here and here.

    The dataSource bean instructs which database to connect to, it is not included in my configuration file as it’s not specific to security. Here is an example of a dataSource bean for those who are not sure:




    1. <bean id=“dataSource” class=“org.springframework.jdbc.datasource.DriverManagerDataSource”>  

    2.     <property name=“driverClassName” value=“com.mysql.jdbc.Driver”/>  

    3.     <property name=“url” value=“jdbc:mysql://localhost/db_name?useUnicode=true&characterEncoding=utf-8”/>  

    4.     <property name=“username” value=“root”/>  

    5.     <property name=“password” value=“pwd”/>  

    6. </bean>  

  5. And that is all for the configuration of Spring Security. My last task was to change my current logon screen. In ACEGI you could create your own logon <form> by making sure that you POSTED the correctly named HTML input elements to the correct URL. While you can still do this in Spring Security 2.0, some of the names have changed.
    You can still call your username field j_username and your password field j_password as before.




    1. <input type=“text” name=“j_username” id=“j_username”/>  

    2. <input type=“password” name=“j_password” id=“j_password”/>  
    However you must set the action property of your <form> to point to j_spring_security_check and notj_acegi_security_check.




    1. <form method=“post” id=“loginForm” action=“<c:url value=’j_spring_security_check’/>”  
    There are a few places in our application where the user can logout, this is a link that redirects the logout request to the security framework so that it can be handled accordingly. This needs to be changed from j_acegi_logout toj_spring_security_logout.




    1. <a href=‘<c:url value=”j_spring_security_logout”/>’>Logout</a>  

Conclusion


This short guide on how to configure Spring Security 2.0 with access to resources stored in a database does not come close to illustrating the host of new features that are available in Spring Security 2.0, however I think that it does show some of the most commonly used abilities of the framework and I hope that you will find it useful.

One of the benefits of Spring Security 2.0 over ACEGI is the ability to write more consice configuration files, this is clearly shown when I compare my old ACEGI configration (172 lines) file to my new one (42 lines).
Here is my complete securityContext.xml file:





  1. <?xml version=“1.0” encoding=“UTF-8”?>  

  2. <beans:beans xmlns=“http://www.springframework.org/schema/security”   

  3. xmlns:beans=“http://www.springframework.org/schema/beans”   

  4. xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”   

  5. xsi:schemaLocation=“http://www.springframework.org/schema/beans,http://www.springframework.org/schema/beans/spring-beans-2.0.xsd,http://www.springframework.org/schema/security,http://www.springframework.org/schema/security/spring-security-2.0.xsd”> <authentication-manager alias=“authenticationManager”/>  <beans:bean id=“accessDecisionManager” class=“org.springframework.security.vote.AffirmativeBased”> <beans:property name=“allowIfAllAbstainDecisions” value=“false”/> <beans:property name=“decisionVoters”> <beans:list> <beans:bean class=“org.springframework.security.vote.RoleVoter”/> <beans:bean class=“org.springframework.security.vote.AuthenticatedVoter”/> </beans:list> </beans:property> </beans:bean> <beans:bean id=“filterInvocationInterceptor” class=“org.springframework.security.intercept.web.FilterSecurityInterceptor”> <beans:property name=“authenticationManager” ref=“authenticationManager”/> <beans:property name=“accessDecisionManager” ref=“accessDecisionManager”/> <beans:property name=“objectDefinitionSource” ref=“secureResourceFilter” /> </beans:bean>  <beans:bean id=“secureResourceFilter” class=“org.security.SecureFilter.MySecureResourceFilter” /> <http auto-config=“true” access-denied-page=“/403.jsp”>  <concurrent-session-control max-sessions=“1” exception-if-maximum-exceeded=“true” /> <form-login login-page=“/login.jsp” authentication-failure-url=“/login.jsp” default-target-url=“/index.jsp” /> <logout logout-success-url=“/login.jsp”/> </http>  <beans:bean id=“loggerListener” class=“org.springframework.security.event.authentication.LoggerListener”/>  <authentication-provider> <jdbc-user-service data-source-ref=“dataSource” users-by-username-query=“SELECT U.username, U.password, U.accountEnabled AS ‘enabled’ FROM User U where U.username=?” authorities-by-username-query=“SELECT U.username, R.name as ‘authority’ FROM User U JOIN Authority A ON u.id = A.userId JOIN Role R ON R.id = A.roleId WHERE U.username=?” /> </authentication-provider> </beans:beans>  

As I said in step 1, downloading Spring Security was the trickiest step of all. From there on it was plain sailing…

Linux/Ubuntu tar命令详解使用格式和方法

格式: tar 选项 文件目录列表
功能: 对文件目录进行打包备份
选项:
-c 建立新的归档文件
-r 向归档文件末尾追加文件
-x 从归档文件中解出文件
-O 将文件解开到标准输出
-v 处理过程中输出相关信息
-f 对普通文件操作
-z 调用gzip来压缩归档文件,与-x联用时调用gzip完成解压缩
-Z 调用compress来压缩归档文件,与-x联用时调用compress完成解压缩



例如:


1.将当前目录下所有.txt文件打包并压缩归档到文件this.tar.gz,我们可以使用


tar czvf this.tar.gz ./*.txt


2.将当前目录下的this.tar.gz中的文件解压到当前目录我们可以使用


tar xzvf this.tar.gz ./


 


利用临时表,加快存储过程的执行速度。

利用临时表,加快存储过程的执行速度。


背景:
  一个博客网站访问流量表,每天有大约100万条数据插入,记录每个博客及网站的访问情况。表结构:
mysql> show fields from blog_track;
+—————-+————–+——+—–+———+—————-+
| Field          | Type         | Null | Key | Default | Extra          |
+—————-+————–+——+—–+———+—————-+
| track_id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| track_ip       | char(15)     | YES  |     | NULL    |                |
| track_date     | datetime     | NO   | MUL |         |                |
| track_page     | varchar(256) | YES  |     | NULL    |                |
| track_refferer | varchar(500) | YES  |     | NULL    |                |
| member_id      | int(11)      | NO   | MUL | 0       |                |
| visiter_id     | int(11)      | NO   |     | 0       |                |
| track_type     | tinyint(4)   | NO   | MUL | 0       |                |
+—————-+————–+——+—–+———+—————-+



每隔2小时就会利用存储过程对这个表进行统计,包括统计当天的IP及PV。


CREATE DEFINER=`root`@`%` PROCEDURE `prc_anaylise_track`()
BEGIN


declare time_now datetime;
DROP TABLE IF EXISTS tmp_tables;
CREATE TEMPORARY TABLE tmp_tables (
blog_id int NOT NULL,
count int NOT NULL,
ip char(15) null
) engine = HEAP;
set time_now = now();
insert into tmp_tables(count,blog_id,ip) select count(*) as count,member_id as blog_id,track_ip as ip  from blog_track where track_type=0 and track_date>=date_format(now(),’%Y-%m-%d 00:00:00′) and member_id>0 group by track_ip,member_id;
update blog_info set blog_info.today_ip = (select count(*) as count from tmp_tables where blog_info.member_id=tmp_tables.blog_id);
delete from tmp_tables;
select concat(‘count today ip count need time : ‘,(unix_timestamp(now()) – unix_timestamp(time_now))) as neetTime;
END


使用了一个临时表保存统计结果,执行时间超过15秒。



下面是使用了两个临时表的代码:


CREATE DEFINER=`root`@`%` PROCEDURE `prc_anaylise_user`()
BEGIN


declare time_now datetime;
DROP TABLE IF EXISTS tmp_tables_full;
CREATE TEMPORARY TABLE tmp_tables_full (
blog_id int not null,
count int not null default 0,
ip char(15) null,
index blog_id(blog_id)
)engine = HEAP;


DROP TABLE IF EXISTS tmp_tables;
CREATE TEMPORARY TABLE tmp_tables (
blog_id int NOT NULL,
count int NOT NULL,
ip char(15) null,
index blog_id(blog_id)
) engine = HEAP;


set time_now = now();
insert into tmp_tables_full(blog_id,ip) select member_id,track_ip  from blog_track where track_type=0 and track_date>=date_format(now(),’%Y-%m-%d 00:00:00′) and member_id>0;
insert into tmp_tables(count,blog_id,ip) select count(*) as count,blog_id,ip  from tmp_tables_full group by blog_id,ip;
update blog_info set blog_info.today_ip = (select count(*) as count from tmp_tables where blog_info.member_id=tmp_tables.blog_id);
delete from tmp_tables_full;
delete from tmp_tables;
select concat(‘count today ip count need time : ‘,(unix_timestamp(now()) – unix_timestamp(time_now))) as neetTime;
END


第一个临时表存放今天的访问记录,第一个临时表存放统计结果。这样做的目的是避免统计时间过长,锁表时间过长,导致网站访问不正常。执行时间为2秒。



进一步优化:
定义一个临时变量,
declare p_updatetime datetime;
建立一个tmpupdatetable表,保存上一次执行的时间;
select updatetime into p_updatetime from tmpupdatetable;
把最后执行的时间回到where条件里:
insert into tmp_tables_full(blog_id,ip) select member_id,track_ip  from blog_track where track_type=0 and track_date>=date_format(now(),’%Y-%m-%d 00:00:00′)  and track_date>=p_updatetime and member_id>0;
更新数据时的代码:
update blog_info set blog_info.today_ip =blog_info.today_ip+ (select count(*) as count from tmp_tables where blog_info.member_id=tmp_tables.blog_id);



经过样的修改,执行时间变了120ms左右。已经符合要求了,如果没有达到这个效果的话,请检查一个blog_track表的索引。


应对20号微软正版验证,Office2003通过正版验证的方法


本文给大家介绍了通过Office2003正版验证的方法,其实还是一个方法……


1.开始-运行-regedit
找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\11.0\Registration\{90110804-6000-11D3-8CFE-0150048383C9}

删除
ProductID
DigitalProductID


2.运行office,出现安装程序,输入FTYBP-J2B4K-K7JHY-3JG2K-MT9VM(或换个其它序列号)

3.去微软官网看是否通过正版验证:www.microsoft.com/Genuine/diag/default.aspx?displaylang=zh-cn

DreamCoder for MySQL 4.4.2 crack 破解 Patch KEYGEN

DreamCoder for MySQL。


  本人一直在使用navicat作为Mysql client,不过navicat写存储过程不太方便,每次写存储过程时都切换到mysql administrator,终于给我发现了一个好东东DreamCoder for MySQL,看了看官网的介绍,抱着一试的态度下载了企业版,感觉非常好,特别在写存储过程,很好很强大。哈哈。。分享给大家。

  终于找到破解版了,Thanks god~

下载:

企业版 http://www.sqldeveloper.net/download/installer_dreamcoder_for_mysql_enterprise.exe
专业版 http://www.sqldeveloper.net/download/installer_dreamcoder_for_mysql_professional.exe
标准版 http://www.sqldeveloper.net/download/installer_dreamcoder_for_mysql_standard.exe
免费版 http://www.sqldeveloper.net/download/installer_dreamcoder_for_mysql_free.exe

 

 


 

 

Mysql日期和时间函数不求人

对于每个类型拥有的值范围以及并且指定日期何时间值的有效格式的描述见7.3.6 日期和时间类型。 

这里是一个使用日期函数的例子。下面的查询选择了所有记录,其date_col的值是在最后30天以内: 

mysql> SELECT something FROM table 
WHERE TO_DAYS(NOW()) – TO_DAYS(date_col) <= 30; 

DAYOFWEEK(date) 
返回日期date的星期索引(1=星期天,2=星期一, ……7=星期六)。这些索引值对应于ODBC标准。 
mysql> select DAYOFWEEK(‘1998-02-03’); 
-> 3 

WEEKDAY(date) 
返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。 
mysql> select WEEKDAY(‘1997-10-04 22:23:00’); 
-> 5 
mysql> select WEEKDAY(‘1997-11-05’); 
-> 2 

DAYOFMONTH(date) 
返回date的月份中日期,在1到31范围内。 
mysql> select DAYOFMONTH(‘1998-02-03’); 
-> 3 

DAYOFYEAR(date) 
返回date在一年中的日数, 在1到366范围内。 
mysql> select DAYOFYEAR(‘1998-02-03’); 
-> 34 

MONTH(date) 
返回date的月份,范围1到12。 
mysql> select MONTH(‘1998-02-03’); 
-> 2 

DAYNAME(date) 
返回date的星期名字。 
mysql> select DAYNAME(“1998-02-05”); 
-> ‘Thursday’ 

MONTHNAME(date) 
返回date的月份名字。 
mysql> select MONTHNAME(“1998-02-05”); 
-> ‘February’ 

QUARTER(date) 
返回date一年中的季度,范围1到4。 
mysql> select QUARTER(’98-04-01′); 
-> 2 

WEEK(date) 
  
WEEK(date,first) 
对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。2个参数形式WEEK()允许
你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1,
从星期一开始。 
mysql> select WEEK(‘1998-02-20’); 
-> 7 
mysql> select WEEK(‘1998-02-20’,0); 
-> 7 
mysql> select WEEK(‘1998-02-20’,1); 
-> 8 

YEAR(date) 
返回date的年份,范围在1000到9999。 
mysql> select YEAR(’98-02-03′); 
-> 1998 

HOUR(time) 
返回time的小时,范围是0到23。 
mysql> select HOUR(’10:05:03′); 
-> 10 

MINUTE(time) 
返回time的分钟,范围是0到59。 
mysql> select MINUTE(’98-02-03 10:05:03′); 
-> 5 

SECOND(time) 
回来time的秒数,范围是0到59。 
mysql> select SECOND(’10:05:03′); 
-> 3 

PERIOD_ADD(P,N) 
增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。 
mysql> select PERIOD_ADD(9801,2); 
-> 199803 

PERIOD_DIFF(P1,P2) 
返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。 
mysql> select PERIOD_DIFF(9802,199703); 
-> 11 

DATE_ADD(date,INTERVAL expr type) 
  
DATE_SUB(date,INTERVAL expr type) 
  
ADDDATE(date,INTERVAL expr type) 
  
SUBDATE(date,INTERVAL expr type) 
这些功能执行日期运算。对于MySQL 3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。
在MySQL 3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)date是一个指定开始日期的
DATETIME或DATE值,expr是指定加到开始日期或从开始日期减去的间隔值一个表达式,expr是一个字符串;它可以以
一个“-”开始表示负间隔。type是一个关键词,指明表达式应该如何被解释。EXTRACT(type FROM date)函数从日期
中返回“type”间隔。下表显示了type和expr参数怎样被关联: type值 含义 期望的expr格式 
SECOND 秒 SECONDS 
MINUTE 分钟 MINUTES 
HOUR 时间 HOURS 
DAY 天 DAYS 
MONTH 月 MONTHS 
YEAR 年 YEARS 
MINUTE_SECOND 分钟和秒 “MINUTES:SECONDS” 
HOUR_MINUTE 小时和分钟 “HOURS:MINUTES” 
DAY_HOUR 天和小时 “DAYS HOURS” 
YEAR_MONTH 年和月 “YEARS-MONTHS” 
HOUR_SECOND 小时, 分钟, “HOURS:MINUTES:SECONDS” 
DAY_MINUTE 天, 小时, 分钟 “DAYS HOURS:MINUTES” 
DAY_SECOND 天, 小时, 分钟, 秒 “DAYS HOURS:MINUTES:SECONDS” 

MySQL在expr格式中允许任何标点分隔符。表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅
包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。 

mysql> SELECT “1997-12-31 23:59:59” + INTERVAL 1 SECOND; 
-> 1998-01-01 00:00:00 
mysql> SELECT INTERVAL 1 DAY + “1997-12-31”; 
-> 1998-01-01 
mysql> SELECT “1998-01-01” – INTERVAL 1 SECOND; 
-> 1997-12-31 23:59:59 
mysql> SELECT DATE_ADD(“1997-12-31 23:59:59”, 
INTERVAL 1 SECOND); 
-> 1998-01-01 00:00:00 
mysql> SELECT DATE_ADD(“1997-12-31 23:59:59”, 
INTERVAL 1 DAY); 
-> 1998-01-01 23:59:59 
mysql> SELECT DATE_ADD(“1997-12-31 23:59:59”, 
INTERVAL “1:1” MINUTE_SECOND); 
-> 1998-01-01 00:01:00 
mysql> SELECT DATE_SUB(“1998-01-01 00:00:00”, 
INTERVAL “1 1:1:1” DAY_SECOND); 
-> 1997-12-30 22:58:59 
mysql> SELECT DATE_ADD(“1998-01-01 00:00:00”, 
INTERVAL “-1 10” DAY_HOUR); 
-> 1997-12-30 14:00:00 
mysql> SELECT DATE_SUB(“1998-01-02”, INTERVAL 31 DAY); 
-> 1997-12-02 
mysql> SELECT EXTRACT(YEAR FROM “1999-07-02”); 
-> 1999 
mysql> SELECT EXTRACT(YEAR_MONTH FROM “1999-07-02 01:02:03”); 
-> 199907 
mysql> SELECT EXTRACT(DAY_MINUTE FROM “1999-07-02 01:02:03”); 
-> 20102 

如果你指定太短的间隔值(不包括type关键词期望的间隔部分),MySQL假设你省掉了间隔值的最左面部分。例如,
如果你指定一个type是DAY_SECOND,值expr被希望有天、小时、分钟和秒部分。如果你象”1:10″这样指定值,
MySQL假设日子和小时部分是丢失的并且值代表分钟和秒。换句话说,”1:10″ DAY_SECOND以它等价于”1:10″ MINUTE_SECOND
的方式解释,这对那MySQL解释TIME值表示经过的时间而非作为一天的时间的方式有二义性。如果你使用确实不正确的日期,
结果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。 

mysql> select DATE_ADD(‘1998-01-30’, Interval 1 month); 
-> 1998-02-28 

注意,从前面的例子中词INTERVAL和type关键词不是区分大小写的。 
TO_DAYS(date) 
给出一个日期date,返回一个天数(从0年的天数)。 
mysql> select TO_DAYS(950501); 
-> 728779 
mysql> select TO_DAYS(‘1997-10-07’); 
-> 729669 

TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。 

FROM_DAYS(N) 
给出一个天数N,返回一个DATE值。 
mysql> select FROM_DAYS(729669); 
-> ‘1997-10-07’ 

TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。 

DATE_FORMAT(date,format) 
根据format字符串格式化date值。下列修饰符可以被用在format字符串中: %M 月名字(January……December) 
%W 星期名字(Sunday……Saturday) 
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。) 
%Y 年, 数字, 4 位 
%y 年, 数字, 2 位 
%a 缩写的星期名字(Sun……Sat) 
%d 月份中的天数, 数字(00……31) 
%e 月份中的天数, 数字(0……31) 
%m 月, 数字(01……12) 
%c 月, 数字(1……12) 
%b 缩写的月份名字(Jan……Dec) 
%j 一年中的天数(001……366) 
%H 小时(00……23) 
%k 小时(0……23) 
%h 小时(01……12) 
%I 小时(01……12) 
%l 小时(1……12) 
%i 分钟, 数字(00……59) 
%r 时间,12 小时(hh:mm:ss [AP]M) 
%T 时间,24 小时(hh:mm:ss) 
%S 秒(00……59) 
%s 秒(00……59) 
%p AM或PM 
%w 一个星期中的天数(0=Sunday ……6=Saturday ) 
%U 星期(0……52), 这里星期天是星期的第一天 
%u 星期(0……52), 这里星期一是星期的第一天 
%% 一个文字“%”。 

所有的其他字符不做解释被复制到结果中。 

mysql> select DATE_FORMAT(‘1997-10-04 22:23:00’, ‘%W %M %Y’); 
-> ‘Saturday October 1997’ 
mysql> select DATE_FORMAT(‘1997-10-04 22:23:00’, ‘%H:%i:%s’); 
-> ’22:23:00′ 
mysql> select DATE_FORMAT(‘1997-10-04 22:23:00’, 
‘%D %y %a %d %m %b %j’); 
-> ‘4th 97 Sat 04 10 Oct 277’ 
mysql> select DATE_FORMAT(‘1997-10-04 22:23:00’, 
‘%H %k %I %r %T %S %w’); 
-> ’22 22 10 10:23:00 PM 22:23:00 00 6′ 
MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。 

TIME_FORMAT(time,format) 
这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。
其他修饰符产生一个NULL值或0。 
CURDATE() 
  
CURRENT_DATE 
以’YYYY-MM-DD’或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。 
mysql> select CURDATE(); 
-> ‘1997-12-15’ 
mysql> select CURDATE() + 0; 
-> 19971215 

CURTIME() 
  
CURRENT_TIME 
以’HH:MM:SS’或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。 
mysql> select CURTIME(); 
-> ’23:50:26′ 
mysql> select CURTIME() + 0; 
-> 235026 

NOW() 
  
SYSDATE() 
  
CURRENT_TIMESTAMP 
以’YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的
上下文被使用。 
mysql> select NOW(); 
-> ‘1997-12-15 23:50:26’ 
mysql> select NOW() + 0; 
-> 19971215235026 

UNIX_TIMESTAMP() 
  
UNIX_TIMESTAMP(date) 
如果没有参数调用,返回一个Unix时间戳记(从’1970-01-01 00:00:00’GMT开始的秒数)。如果UNIX_TIMESTAMP()用一
个date参数被调用,它返回从’1970-01-01 00:00:00′ GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME
字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地时间的一个数字。 
mysql> select UNIX_TIMESTAMP(); 
-> 882226357 
mysql> select UNIX_TIMESTAMP(‘1997-10-04 22:23:00’); 
-> 875996580 

当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换。 

FROM_UNIXTIME(unix_timestamp) 
以’YYYY-MM-DD HH:MM:SS’或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串
还是或数字上下文中被使用。 
mysql> select FROM_UNIXTIME(875996580); 
-> ‘1997-10-04 22:23:00’ 
mysql> select FROM_UNIXTIME(875996580) + 0; 
-> 19971004222300 

FROM_UNIXTIME(unix_timestamp,format) 
返回表示 Unix 时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条
目同样的修饰符。 
mysql> select FROM_UNIXTIME(UNIX_TIMESTAMP(), 
‘%Y %D %M %h:%i:%s %x’); 
-> ‘1997 23rd December 03:43:30 x’ 

SEC_TO_TIME(seconds) 
返回seconds参数,变换成小时、分钟和秒,值以’HH:MM:SS’或HHMMSS格式化,取决于函数是在一个字符串还是在数字
上下文中被使用。 
mysql> select SEC_TO_TIME(2378); 
-> ’00:39:38′ 
mysql> select SEC_TO_TIME(2378) + 0; 
-> 3938 

TIME_TO_SEC(time) 
返回time参数,转换成秒。 
mysql> select TIME_TO_SEC(’22:23:00′); 
-> 80580 
mysql> select TIME_TO_SEC(’00:39:38′); 
-> 2378