Tuesday, November 2, 2010

本机上创建多个基于域名的虚拟主机

这是一些配置文件,使用这些配置文件后,就可使用eclipse来访问Eclipse建立的项目目录,而使用old则访问用户目录中的Apache2目录。
这是一个使用Apache2的基于域名的多个虚拟主机创建实例。但遗憾的是Apache在运行时,会有一个小小的警告
* Reloading web server config apache2
apache2: Could not reliably determine the server's fully
qualified domain name, using 127.0.1.1 for ServerName
不过,这些都素浮云,因为伊可以正常运行了。
127.0.0.1 localhost
127.0.1.1 westnorth-tablet
127.0.1.2 eclipse
127.0.1.3 old
192.168.1.100 pc1
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
/////////////etc/hosts


#NameVirtualHost 127.0.1.3
<VirtualHost *:80>
ServerAdmin webmaster@localhost
# ServerName old
DocumentRoot /home/westnorth/apache2
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /home/westnorth/apache2/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog /var/log/apache2/access.log combined

Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>

</VirtualHost>
#########################/etc/apache2/default

NameVirtualHost 127.0.1.2
<VirtualHost 127.0.1.2>
ServerAdmin webmaster@localhost
ServerName eclipse
DocumentRoot /home/westnorth/workspace/php
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /home/westnorth/workspace/php/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog /var/log/apache2/access.log combined

Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>

</VirtualHost>
#############################/etc/apache2/site-availvabale/eclipse

Monday, November 1, 2010

再续

记忆力越来越差了,证明了记笔记的重要性。没自己写,找了个现成的,注意红色部分。

引用:
随便找个项目里的py文件以"Python Run"方式运行一下。然后右键点项目,选择"Debug as",在第2个输入框右侧点"Browser",选择Google App Engine文件夹里的dev_appserver.py文件(最终路径类似于${workspace_loc:keakon/appengine/dev_appserver.py})。切换到"Arguments"标签,填入"."(不含引号)。

前篇之续

前面有点内容没有提,补一下。

安装Pydev后,还需要在Eclipse中设置一下Python的运行环境。
打开菜单windows->preference,在Interpreter-Python中,单击New按钮,选择Python的安装位置,Ubuntu的在/usr/bin/python,下面的system
PYTHONPATH中会出现Python的的系统库的一些目录,要注意的是里面的版本号应该是2.5.这样,就完成了Pydev的设置。

使用pydev插件在Eclipse调用Google App Engine开发Python

突然对Google App Engine(GAE)感兴趣,于是准备在Eclipse中进行试验,但其实噩梦刚刚开始。
遇到的问题有:
1.GAE在Eclipse中插件无法正常安装。
2.Pydev建立的GAE项目无法正常运行。
安装GAE插件,可以使用地址:http://dl.google.com/eclipse/plugin/3.6
,这是对应于Eclipse的3.6,如果是3.5中需要简单修改数字即可。
安装的方法是单击Eclipse的Help,选择"Install new
software",然后,单击Add按钮,在Location中输入地址,在Name中输入描述信息,单击OK会显示可以安装的软件列表,选择要安装的软件,如果不确定,可以全部选择。然后进行安装。不知怎么搞的,我的Eclipse安装GAE插件始终会报错。不过,实践证明,在以后的使用过程中,发现可以使用Python进行开发。

现在我使用的是Ubuntu10.04,这个版本安装的Python是2.6版本,但GAE需要2.5,所以需要再建立一个2.5的Python。其他下载方法比较混乱,最简单的方法是加入一个有2.5的源即可。在/etc/apt/source.list中加入deb
http://security.ubuntu.com/ubuntu hardy-security
main,然后,update一下,就可以使用apt-get进行安装了。截至目前(2010年11月1日)为至,最新的SDK还不太支持Python2.6,所以安装2.5还是必须的。

现在安装Pydev,在Eclipse中的安装地址是http://pydev.sf.net/updates/。这个比较简单。

现在开始新建一个项目,可以选择Pydev中的GAE项目,创建的过程也比较简单。复杂的是如何让它运行起来。
一般来说,应遵循如下步骤:
1.首先,选择一个Python文件,单击Run按钮,使其运行一次。
2.右键单击项目,选择新建文件夹,在Folder Name中随便输入一个名字,如GAE。
3.单击Advanced按钮,选择Link to the Alternate Location。单击其后的Browser,选择GAE的目录。
前面是为了将GAE链接到工程中来。
4.右键单击项目,选择Debug as-》debug configuration,在Main
Module中,选择GAE目录(刚才新建的包含了GAE SDK的目录)中的dev_appserver.py文件。
5.单击Debug按钮则服务开始运行。
6.在运行前,可能在Console中会出现一些提示,问要不要在运行前更新之类,输入yes或no(按自己的需要)
7.在运行提示中,会发现服务运行于哪个端口,一般是8080。在浏览器中输入 localhost:8080,就可以看到一个简单的示例输出。

Friday, August 20, 2010

使用git同步代码

git是一个代码同步工具。
  1. 1.安装git
Ubuntu中的git-core有许多工具是没有的,所以应该下载一个git的deb包进行安装。
  1. 2.安装ssh
同步有许多方法,有http,也可以使用ssh。我使用的是ssh。
首先,安装一个ssh服务,名字叫openssh-server。安装后自动启动。
然后在客户机上使用ssh-keygen -t rsa生成一个密钥,在生成时,密码掩码要留空,这样就可自动登录。
生成一个名为id_rsa.pub(?),的文件,该 文件位于.ssh目录中,将这个文件发送到服务器的.ssh目录中,更名为authorized_keys,然后重新使用ssh登录,会发现已经不要密码了。现在准备工作作完,开始部署服务器。
  1. 3.部署git服务
首先,要在服务器端创建名为/var/cache/git/workspace.git的目录,这个是必须的。
然后要给该目录一个权限。
cd  /var/cache/git/workspace.git
chown -R root:www-data ./
而且要将当前用户加入到www-data组之中。
在该目录中生成一个git反响:
git --bare init
chmod g+rwx -R ./
  1. 4.客户端向服务器添加代码
客户端操作:
进入一个不是workspace的目录。创设是code。
执行:
会将服务器同步下来。由于服务器中并无代码,所以我们还需要加入一些代码。
(1)将代码复制到code目录。
(2)git add ./,这样就会将当前目录中的所有代码添加到git中。
(3)git commit -m 'init' ,第2步并未真正提交代码,这是提交的命令
 (4)git push origin master ,将本地作为master分支提交到服务器的origin中。这两个关键词都不能更改。这是第一次,执行完后,以后就可直接git push了。
现在,就将本地的代码同步到服务器上了。
  1. 5.从任意客户端获取代码
现在,任意客户端(安装了git的机器),进入到一个要获取代码的目录。
然后,
就会将我们上传到服务器的代码同步到本机。
然后我们也可以参照上一节的操作上传代码了。

注意:Eclipse的代码有点特别。如果要从服务器同步代码的话。那么,不能将同步来的项目代码放置在这Eclipse的项目默认目录(一般是~/workspace),否则在打开项目文件时会报错。放置在另外的其他目录就没任何问题了。
 







使用按钮打开一个activity

For example, inside the onCreateOptionsMenu() method, you can define a new menu item with an Intent like this:

  MenuItem menuItem = menu.add(0, PHOTO_PICKER_ID, 0, "Select Photo");
menuItem
.setIntent(new Intent(this, PhotoPicker.class));
  这是SDK中的一段话,意思是可以在创建菜单时使用SetIntent来使该项可打开一个Activity.
  

关于组菜单的操作

在菜单创建代码后面加上如下一句,则会使一组菜单成为单选状态。
 menu_send.setGroupCheckable(0, true, true);

代码:
      menu.setHeaderTitle(R.string.backup_conmenu);
            SubMenu menu_send=menu.addSubMenu("send");
            menu_send.add(0,menu_email,0,"email");
            menu_send.add(0,menu_wifi,0,"wifi");
            menu_send.setGroupCheckable(0, true, true);
            menu_send.setGroupEnabled(0, false);


SDK中的一句话应该如何理解:

This will display a checkbox with the menu item (unless it's in the Icon Menu). When the item is selected, the onOptionsItemSelected() callback is called as usual. It is here that you must set the state of the checkbox. You can query the current state of the item with isChecked() and set the checked state with setChecked(). Here's what this looks like inside theonOptionsItemSelected() callback:

  switch (item.getItemId()) {
case VIBRATE_SETTING_ID:
 
if (item.isChecked()) item.setChecked(false);
 
else item.setChecked(true);
 
return true;
...这里为什么要不断设置单选框的状态?
}
我在实际代码中这样:

    @Override
    public boolean onContextItemSelected(MenuItem item) {
//      AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    TextView tview3=(TextView)findViewById(R.id.hello);
     switch (item.getItemId()) {
      case menu_email:
      tview3.setText("your data will send by email");
        return true;
      case menu_wifi:
      tview3.setText("your data will send by wifi");
        return true;
      case menu_apple:
      if (item.isChecked()) item.setChecked(false);
      else item.setChecked(true);
      tview3.setText("your favorite is apple");
      return true;
      case menu_pear:
      if (item.isChecked()) item.setChecked(false);
      else item.setChecked(true);
      tview3.setText("your favorite is pear");
      return true;
      case menu_ear:
      if (item.isChecked()) item.setChecked(false);
      else item.setChecked(true);
      tview3.setText("your favorite is ear");
      
      return true;
      case menu_egg:
//      if (item.isChecked()) item.setChecked(false);
//      else item.setChecked(true);
      tview3.setText("your favorite is egg");
      return true;
      default:
        return super.onContextItemSelected(item);
      }
     }

似乎也没有什么问题。

关于菜单组,我的理解错误

菜单组的状态设置,应该是在创建菜单时设置。
代码:
            menu.setHeaderTitle(R.string.backup_conmenu);
            SubMenu menu_send=menu.addSubMenu("send");
            menu_send.add(0,menu_email,0,"email");
            menu_send.add(0,menu_wifi,0,"wifi");
            menu_send.setGroupEnabled(0, false);
这样就可以进行设置了。
思路应该是创建菜单时,根据某些条件动态设置一些菜单组为不可用,或选中状态之类。
下面一句来自SDK:
You can show or hide the entire group with setGroupVisible(); enable or disable the group withsetGroupEnabled(); and set whether the items can be checkable with setGroupCheckable().

菜单组的几个命令如何使用

Android的菜单组,有几个命令是用来控制菜单组的。但是,菜单只有在创建时才有组的概念。在其他的Activity中也可能通过组id来对该组进行设置吗?这样的话,组编号在整个软件的生命周期中是唯一了?
当使用时,却发现提示,说setGroupEnabled函数并未定义。不知是什么原因。

Wednesday, August 18, 2010

动态生成菜单的一段还末理解的代码

这段代码暂时看不太懂,先记下来。等看了intent的内容后再回头看。 
  @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        final boolean haveItems = getListAdapter().getCount() > 0;

        // If there are any notes in the list (which implies that one of
        // them is selected), then we need to generate the actions that
        // can be performed on the current selection.  This will be a combination
        // of our own specific actions along with any extensions that can be
        // found.
        if (haveItems) {
            // This is the selected item.
            Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());

            // Build menu...  always starts with the EDIT action...
            Intent[] specifics = new Intent[1];
            specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
            MenuItem[] items = new MenuItem[1];

            // ... is followed by whatever other actions are available...
            Intent intent = new Intent(null, uri);
            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
                    items);

            // Give a shortcut to the edit action.
            if (items[0] != null) {
                items[0].setShortcut('1', 'e');
            }
        } else {
            menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
        }

        return true;
    }

使用xml文件创建菜单的事件处理函数

使用xml文件创建的菜单程序,在使用 swtch捕捉用户点击时,要使用形似R.id.opmen1之类的变量才可正确捕捉。
函数如下:
 public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.opmenu1:
//            newGame();
         int i=0;
            return true;
        case R.id.opmenu2:
//            quit();
         int j=1;
            return true;
        }
        return false;
    }

Friday, August 13, 2010

错误:Java Model Status [gen [****]does not exist]

在使用Eclipse的过程中,突然所有项目都出现了错误,提示是:
Java Model Status [gen [****]does not exist]
后来,将gen目录(包括其中的文件R)删除,故障排除。不知是什么原因。

网上说,也可以更换一下SDK的版本来解决这个问题。

Friday, July 23, 2010

复杂的一些菜单代码(来自系出名门)

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello Layout</string>
<string name="app_name">webabcd_layout</string>
</resources>

Main.java
package com.webabcd.layout;

import android.app.Activity;
import android.os.Bundle;

public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

2、上下文菜单,选项菜单,子菜单
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">

<TextView android:id="@+id/txt1" android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello_contextMenu" />

<TextView android:id="@+id/txt2" android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello_subMenu" />

</LinearLayout>

res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello_contextMenu">Hello Context Menu</string>
<string name="hello_subMenu">Hello Context Sub Menu</string>
<string name="app_name">webabcd_menu</string>
</resources>

Main.java
package com.webabcd.menu;

import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.TextView;
import android.widget.Toast;

// 演示两种菜单的实现方式:上下文菜单(通过在某元素上长按,来呼出菜单)和选项菜单(通过按手机上的菜单按钮,来呼出菜单)
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// 为 R.id.txt1 注册一个上下文菜单(在此 TextView 上长按,则会呼出上下文菜单)
// 具体呼出的菜单内容需要重写 onCreateContextMenu 来创建
TextView txt1 = (TextView) this.findViewById(R.id.txt1);
this.registerForContextMenu(txt1);

// 为 R.id.txt2 注册一个上下文菜单
TextView txt2 = (TextView) this.findViewById(R.id.txt2);
this.registerForContextMenu(txt2);
}

// 重写 onCreateContextMenu 用以创建上下文菜单
// 重写 onContextItemSelected 用以响应上下文菜单
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);

// 创建 R.id.txt1 的上下文菜单
if (v == (TextView) this.findViewById(R.id.txt1)) {

// ContextMenu.setIcon() - 设置菜单的图标
// ContextMenu.setHeaderTitle() - 设置菜单的标题
menu.setHeaderIcon(R.drawable.icon01);
menu.setHeaderTitle("我是菜单");

// 用 ContextMenu.add() 来增加菜单项,返回值为 MenuItem
// 第一个参数:组ID
// 第二个参数:菜单项ID
// 第三个参数:顺序号
// 第四个参数:菜单项上显示的内容
menu.add(1, 0, 0, "菜单1");

// MenuItem - 新增菜单项后的返回类型,针对菜单项的其他设置在此对象上操作
menu.add(1, 1, 1, "菜单2").setCheckable(true);

}
// 创建 R.id.txt2 的上下文菜单(多级上下文菜单)
else if (v == (TextView) this.findViewById(R.id.txt2)) {

// ContextMenu.addSubMenu("菜单名称") - 用来添加子菜单。子菜单其实就是一个特殊的菜单
SubMenu sub = menu.addSubMenu("父菜单1");
sub.setIcon(R.drawable.icon01);
sub.add(0, 0, 0, "菜单1");
sub.add(0, 1, 1, "菜单2");
sub.setGroupCheckable(1, true, true);

SubMenu sub2 = menu.addSubMenu("父菜单2");
sub2.setIcon(R.drawable.icon01);
sub2.add(1, 0, 0, "菜单3");
sub2.add(1, 1, 1, "菜单4");
sub2.setGroupCheckable(1, true, false);

}
}


// 重写 onCreateOptionsMenu 用以创建选项菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {

MenuItem menuItem = menu.add(0, 0, 0, "菜单111111111111111111111");

// MenuItem.setIcon() - 设置菜单项的图标
// MenuItem.setTitleCondensed() - 菜单的简标题,如果指定了简标题的话,菜单项上的标题将会以此简标题为准
// MenuItem.setAlphabeticShortcut() - 设置选中此菜单项的快捷键
// 注:菜单项超过 6 个的话,第 6 个菜单将会变为 More 菜单,多余的菜单会在单击 More 菜单之后显示出来
menuItem.setIcon(R.drawable.icon01);
menuItem.setTitleCondensed("菜单1");
menuItem.setAlphabeticShortcut('a');

menu.add(0, 1, 1, "菜单2").setIcon(R.drawable.icon02);
menu.add(0, 2, 2, "菜单3").setIcon(R.drawable.icon03);
menu.add(0, 3, 3, "菜单4");
menu.add(0, 4, 4, "菜单5");
menu.add(0, 5, 5, "菜单6");
menu.add(0, 6, 6, "菜单7").setIcon(R.drawable.icon04);
menu.add(0, 7, 7, "菜单8").setIcon(R.drawable.icon05);

return true;
}

// 重写 onOptionsItemSelected 用以响应选项菜单
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);

Toast.makeText(Main.this, "被单击的菜单项为:" +
String.valueOf(item.getItemId()), Toast.LENGTH_SHORT).show();

return false;
}
}

OK

创建一个上下文菜单

创建一个上下文菜单的代码如下,注意要先定义EDIT_ID与DELETE_ID的值.
但完成代码后,在界面中长按,并没有弹出相应的菜单,不知是为什么.
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, EDIT_ID, 0,"Edit");
menu.add(0, DELETE_ID, 0,"Delete");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)
item.getMenuInfo();
switch (item.getItemId()) {
case EDIT_ID:
// editNote(info.id);
return true;
case DELETE_ID:
// deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
答案是,在使用content菜单时,要先进行注册。以表示该上下文菜单是对应于哪一个控件。函数是:
registerForContextMenu。
这个函数一般被加在OnCreate中,示例如下:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tView=(TextView)findViewById(R.id.hello);
registerForContextMenu(tView);
}
这是给系统创建的默认页面的默认元素(是一个TextView)加一个上下文菜单的例子。加入这些代码后,就可在程序的主页面中测试到上下文菜单了。

Monday, July 19, 2010

intent 用法(来自eoe)

Android Intent的几种用法全面总结

Intent, 用法
Intent应该算是Android中特有的东西。你可以在Intent中指定程序要执行的动作(比如:view,edit,dial),以及程序执行到该动作时所需要的资料。都指定好后,只要调用startActivity(),Android系统会自动寻找最符合你指定要求的应用程序,并执行该程序。

下面列出几种Intent的用法
显示网页:
Uri uri = Uri.parse("http://www.google.com");
Intent it = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);

显示地图:
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW,uri);
startActivity(it);

路径规划:
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intent it = new Intent(Intent.ACTION_VIEW,URI);
startActivity(it);

拨打电话:
调用拨号程序
Uri uri = Uri.parse("tel:xxxxxx");
Intent it = new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);

Uri uri = Uri.parse("tel.xxxxxx");
Intent it =new Intent(Intent.ACTION_CALL,uri);
要使用这个必须在配置文件中加入<uses-permission id="android.permission.CALL_PHONE" />

发送SMS/MMS
调用发送短信的程序
Intent it = new Intent(Intent.ACTION_VIEW);
it.putExtra("sms_body", "The SMS text");
it.setType("vnd.android-dir/mms-sms");
startActivity(it);

发送短信
Uri uri = Uri.parse("smsto:0800000123");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
it.putExtra("sms_body", "The SMS text");
startActivity(it);

发送彩信
Uri uri = Uri.parse("content://media/external/images/media/23");
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra("sms_body", "some text");
it.putExtra(Intent.EXTRA_STREAM, uri);
it.setType("image/png");
startActivity(it);

发送Email

Uri uri = Uri.parse("mailto:xxx@abc.com");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);

Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.setType("text/plain");
startActivity(Intent.createChooser(it, "Choose Email Client"));

Intent it=new Intent(Intent.ACTION_SEND);
String[] tos={"me@abc.com"};
String[] ccs={"you@abc.com"};
it.putExtra(Intent.EXTRA_EMAIL, tos);
it.putExtra(Intent.EXTRA_CC, ccs);
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.setType("message/rfc822");
startActivity(Intent.createChooser(it, "Choose Email Client"));

添加附件
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));

播放多媒体

Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/song.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,
"1");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);

Uninstall 程序
Uri uri = Uri.fromParts("package", strPackageName, null);
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);

eoeAndroid
Android中的Intent详细讲解
不错,我再补充几个:
uninstall apk
Uri uninstallUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);


install apk
Uri installUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

play audio
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");

returnIt = new Intent(Intent.ACTION_VIEW, playUri);

//发送附件
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));

market相关

再来一个market相关的:
market相关

//搜索应用
Uri uri = Uri.parse("market://search?q=pname:pkg_name");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where pkg_name is the full package path for an application

//显示指定应用的详细页面(这个好像不支持了,找不到app_id)
Uri uri = Uri.parse("market://details?id=app_id");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where app_id is the application ID, find the ID
//by clicking on your application on Market home
//page, and notice the ID from the address bar

Salute


原作者:
来源Datatypes In SQLite Version 3
译者边之龙

大多数 SQL 数据库引擎(据我们所知的、SQLite 以外的所有 SQL 数据库引擎)使用静态的、严格的类型。对于静态类型,数据类型的值由它的容器(存储值的特定列)来决定。

SQLite 使用的是一个更加普通的动态类型系统。在 SQLite 中,数据类型的值是与值的本身有关联,而不是它的容器。SQLite 的动态类型系统对于更多其它数据库引擎常见的静态类型系统是向后兼容的,在这个意义上,工作在静态类型数据库上的 SQL 语句同样也能工作在 SQLite 中。然而,SQLite 中的动态类型允许它做一些在传统严格类型数据库中不能做的事情。

1.0 存储类和数据类型

存储在 SQLite 数据库中的每个值(或者由数据库引擎操纵的值)都是以下的存储类之一:
  • NULL。该值是一个 NULL 值。
  • INTEGER。该值是一个有符号的整数,根据值的大小,存储 1、2、3、4、5、6 或 8 字节内容。
  • REAL。该值是一个浮点值,存储一个 8 字节的 IEEE 浮点数。
  • TEXT。该值是一个文本字符串,使用数据库编码(UTF-8、 UTF-16BE 或 UTF-16LE)进行存储。
  • BLOB。该值是一个数据块,按照它的输入直接存储。

注意,一个存储类要略普遍于一个数据类型。INTEGER 存储类,例如,包含不同长度的 6 个不同的整数类型。这在磁盘上是不同的。但是一旦 INTEGER 值从磁盘读取到内存进行处理,它们都将被转换为最普通的数据类型(8 字节有符号的整数)。因此大部分"存储类"是无异于"数据类型"的,并且有 2 个条款能被互换地使用。

在一个 SQLite 版本 3 数据库中的任何列,除了 INTEGER PRIMARY KEY 列,都可以被用来存储一个任意存储类的值。

SQL 语句中的所有值,无论它们是嵌入在 SQL 语句文本里的字面量,还是绑定到预编译 SQL 语句的参数,都有一个内在存储类。在以下描述的情况中,数据库引擎会在执行查询过程中,在数字存储类(INTEGER 和 REAL)和 TEXT 之间进行转换。

1.1 Boolean 数据类型

SQLite 没有一个分开的 Boolean 存储类。替代的,Boolean 值被存储为整数 0(false)和 1(true)。

1.2 Date 和 Time 数据类型

SQLite 没有一个预留的存储日期和/或时间的存储类。替代的,SQLite 内置的 Date 和 Time 函数有能力把日期和时间存储为 TEXT、REAL 或 INTEGER 值:

  • TEXT 为 ISO8601 字符串(YYYY-MM-DD HH:MM:SS.SSS)。
  • REAL 为"朱利安"天数,天数从"格林威治"公元前4714年11月24日中午到预期的公历。
  • INTEGER 为 Unix Time,自 1970-01-01 00:00:00 UTC 以来的秒数。

应用程序可以选择任何格式来存储日期和时间,并且使用内置的日期和时间函数在格式之间自由地转换。

2.0 亲和类型

为了最大化 SQLite 和其它数据库引擎之间的兼容性,SQLite 支持列上的"亲和类型"概念。一个列的亲和类型是存储在该列的数据的推荐类型。在这里最重要的是,类型是被推荐的,而不是必须的。所有列仍可以存储任意类型的数据。这只是一些列,给出选择,将会使用一个存储类覆盖原先的。一个列首选的存储类称为它的"亲和类型"。

SQLite 3 数据库中的每个列被分配了以下亲和类型之一:

  • TEXT
  • NUMERIC
  • INTEGER
  • REAL
  • NONE

一个带有 TEXT 亲和类型的列,可以使用存储类 NULL、TEXT、BLOB 来存储所有的数据。如果数值数据被插入到一个带有 TEXT 亲和类型的列中,它将从原来被存储的格式转换为现在的文本格式。

一个带有 NUMERIC 亲和类型的列可以包含所有的 5 种存储类。当文本数据被插入到一个 NUMERIC 列中,如果转换是无损和可逆的,文本存储类将被转换为 INTEGER 或 REAL(优先顺序)。对于 TEXT 和 REAL 存储类之间的转换,如果数的前 15 位是有意义的十进制数字,SQLite 考虑到转换要无损和可逆,都将会被保留。如果 TEXT 到 INTEGER 或 REAL 的无损转换是不可能的,那么值将使用 TEXT 存储类进行存储。不要尝试将其转换为 NULL 或 BLOB 值。

一个字符串可能看起来像一个带有小数点和/或指数符号的浮点数字面量,但只要该值能够被表示为一个整数,NUMERIC 亲和类型会将转换它为一个整数。因此,在一个 NUMERIC 亲和类型的列中,字符串 '3.0e+5' 被存储为整数 300000,而不是浮点值 300000.0。

一个使用 INTEGER 亲和类型的列与一个使用 NUMERIC 亲和类型的列在行为上是相同的。INTEGER 和 NUMERIC 亲和类型不同点只表现在一个 CAST 表达式上。

一个带有 REAL 亲和类型的列与一个带有 NUMERIC 亲和类型的列在行为上是相同的,除了它强制把整数值作为浮点数来表示。(作为一个内部的优化,没有小数部分的小浮点数值存储到带有 REAL 亲和类型的列中时,将被作为一个整数写入到磁盘,为的是占用更少的空间和在它被读出时能被自动地转换回浮点数。该优化在 SQL 级别是完全不可见的,并且只有通过研究数据库文件的原始数据才能被检测。)

一个带有 NULL 亲和类型的列不建议将一个存储类覆盖到另一个存储类,并且不要尝试强制将数据从一个存储类变为另一个存储类。

2.1 亲和列的测定

一个列的亲和类型是由列的声明类型决定的,根据下面展示的有顺序的规则:

  1. 如果类型声明包含字符串"INT",它将被分配为 INTEGER 亲和类型。
  2. 如果列的类型声明包含字符串"CHAR"、"CLOB"或"TEXT"的任意之一,列将拥有 TEXT 亲和类型。
  3. 如果一个列的类型声明包含字符串"BLOB",或者如果没有类型被指定,列将拥有 NONE 亲和类型。
  4. 如果一个类的类型声明包含字符串"REAL"、"FLOA"或"DOUB"的任意之一,列将拥有 REAL 亲和类型。
  5. 否则,亲和类型为 NUMERIC。

注意,决定列的亲和类型的规则的顺序是十分重要的。一个列的类型声明若是"CHARINT",则将匹配规则 1 和 2,但是第一个规则更加优先,因此列的亲和类型为 INTEGER。

2.2 亲和名称的例子

下表展示了,如何通过前一章节的 5 个规则,将传统的 SQL 实现的通用数据类型名称转换为亲和的类型。该表只展示了 SQLite 允许的数据类型名称的一个小子集。注意,类型名称后面括号中的数字参数(如:"VARCHAR(255)")将被 SQLite 忽略 - SQLite 不会在全局 SQLITE_MAX_LENGTH 以外,再对字符串、BLOBs 或数字值的长度上强加任何的长度限制。


来自 CREATE TABLE 语句 CAST 表达式中
类型名称的例子
亲和类型结果被用来决定亲和类型的规则
INT
INTEGER
TINYINT
SMALLINT
MEDIUMINT
BIGINT
UNSIGNED BIG INT
INT2
INT8
INTEGER1
CHARACTER(20)
VARCHAR(255)
VARYING CHARACTER(255)
NCHAR(55)
NATIVE CHARACTER(70)
NVARCHAR(100)
TEXT
CLOB
TEXT2
BLOB
no datatype specified
NONE3
REAL
DOUBLE
DOUBLE PRECISION
FLOAT
REAL4
NUMERIC
DECIMAL(10, 5)
BOOLEAN
DATE
DATETIME
NUMERIC5

注意,一个"FLOATING POINT"类型声明会给出 INTEGER 亲和类型,而不是 REAL 亲和类型,由于"POINT"的结尾是"INT"。并且类型声明"STRING"将是一个 NUMBERIC 亲和类型,而不是 TEXT。

2.3 列亲和行为的例子

下面的 SQL 演示了 SQLite 在值被插入到一个表时,如何使用列的亲和类型来进行类型转换。

CREATE TABLE t1(
    t  TEXT,     -- 规则 2 的文本亲和类型
    nu NUMERIC,  -- 规则 5 的数字亲和类型
    i  INTEGER,   -- 规则 1 的整数亲和类型
    r  REAL,     -- 规则 4 的浮点数亲和类型
    no BLOB      -- 规则 3 的无亲和类型
);
  
-- 值被存储为 TEXT、INTEGER、INTEGER、REAL、TEXT。
INSERT INTO t1 VALUES('500.0', '500.0', '500.0', '500.0', '500.0');
SELECT typeof(t), typeof(nu), typeof(i), typeof(r), typeof(no) FROM t1;
text|integer|integer|real|text
  
-- 值被存储为 TEXT、INTEGER、INTEGER、REAL、REAL。
DELETE FROM t1;
INSERT INTO t1 VALUES(500.0, 500.0, 500.0, 500.0, 500.0);
SELECT typeof(t), typeof(nu), typeof(i), typeof(r), typeof(no) FROM t1;
text|integer|integer|real|real
  
-- 值被存储为 TEXT、INTEGER、INTEGER、REAL、INTEGER。
DELETE FROM t1;
INSERT INTO t1 VALUES(500, 500, 500, 500, 500);
SELECT typeof(t), typeof(nu), typeof(i), typeof(r), typeof(no) FROM t1;
text|integer|integer|real|integer
  
-- 无论列的亲和类型,BLOBs 总是被存储为 BLOBs。
DELETE FROM t1;
INSERT INTO t1 VALUES(x'0500', x'0500', x'0500', x'0500', x'0500');
SELECT typeof(t), typeof(nu), typeof(i), typeof(r), typeof(no) FROM t1;
blob|blob|blob|blob|blob
  
-- NULLs 也不会被亲和类型所影响。
DELETE FROM t1;
INSERT INTO t1 VALUES(NULL,NULL,NULL,NULL,NULL);
SELECT typeof(t), typeof(nu), typeof(i), typeof(r), typeof(no) FROM t1;
null|null|null|null|null

3.0 比较表达式

SQLite 版本 3 有通常的 SQL 比较操作符集,包括"="、"<"、"<="、">="、"!="、"IN"、"BETWEEN"和"IS"等。

3.1 排序顺序

一个比较的结果是依靠操作数的存储类来决定的,根据下面的规则:

  • 存储类 NULL 的值被认为是小于其它任何值的(包括其它存储类 NULL 的值)。
  • 一个 INTEGER 或 REAL 值小于任何 TEXT 或 BLOB 值。当一个 INTEGER 或 REAL 与其它 INTEGER 或 REAL 比较时,一个数值的比较将被执行。
  • 一个 TEXT 值是小于一个 BLOB 值的。当两个 TEXT 值进行比较时,一个适当的集合序列将被用来决定其结果。
  • 当两个 BLOB 值进行比较时,使用 memcmp() 来决定结果。

3.2 比较操作数的亲和类型

SQLite 在执行一个比较之前,会尝试在存储类 INTEGER、REAL 和/或 TEXT 之间执行值的转换。在比较发生之前,无论尝试任何转换,都是依靠操作数的亲和类型而进行的。操作数的亲和类型是由以下规则决定的:

  • 一个表达式是一个对列值的简单引用,则拥有与列相同的亲和类型。注意,如果 X 和 Y.Z 是列名,那么 +X 和 +Y.Z 将被认为是表达式,目的是为了确定亲和类型。
  • 一个"CAST(expr TO type)"格式的表达式,拥有与一个列的"type"类型声明相同的亲和类型。
  • 否则,表达式为 NONE 亲和类型。

3.3 比较之前的类型转换

要"应用亲和类型"意思是转换一个操作数为一个特定的存储类,当且仅当转换是无损和可逆的。要在比较之前将亲和类型应用到一个比较操作符的操作数中,根据以下展示的规则顺序:

  • 如果一个操作数为 INTEGER、REAL 或 NUMERIC 亲和类型,并且另一个操作数为 TEXT 或 NONE 亲和类型,NUMERIC 亲和类型将被应用到另一个操作数上。
  • 如果一个操作数为 TEXT 亲和类型,并且另一个操作数为 NONE 亲和类型,TEXT 亲和类型将被应用到另一个操作数上。
  • 否则,无亲和类型将被应用到两个比较的操作数上。

表达式"a BETWEEN b AND c"被视为两个分开的二元比较"a >= b AND a <= c",即使这意味着不同的亲和类型被应用到每个比较的"a"上。格式"x IN (SELECT y ...)"比较中的数据类型转换,被处理为"x = y"是否为真。表达式"a IN (x, y, z, ...)"相当于"a = +x, a = +y, a = +z, ..."。换句话讲,IN 操作符右边的值(该例中为"x"、"y"和"z"的值)将被视为无亲和类型,即使它们碰巧是列值或 CAST 表达式。

3.4 比较示例

CREATE TABLE t1(
    a TEXT,      -- 文本亲和类型
    b NUMERIC,   -- 数字亲和类型
    c BLOB,      -- 无亲和类型
    d            -- 无亲和类型
);

-- 值将分别被存储为 TEXT、INTEGER、TEXT 和 INTEGER。
INSERT INTO t1 VALUES('500', '500', '500', 500);
SELECT typeof(a), typeof(b), typeof(c), typeof(d) FROM t1;
text|integer|text|integer

-- 因为列"a"是文本亲和类型,右手边的数字值在发生比较之前,就被转换为文本了。
SELECT a < 40,   a < 60,   a < 600 FROM t1;
0|1|1

-- 文本亲和类型被应用到右手边的操作数,但因为它们已经是 TEXT,这将是一个空操作;不会发生转换。
SELECT a < '40', a < '60', a < '600' FROM t1;
0|1|1

-- 列"b"是数字亲和类型,因此数字亲和类型将被应用给右边的操作数。因为操作数已经是数字,应用程序的亲和类型将是空操作;不会发生转换。所有值进行数值比较。
SELECT b < 40,   b < 60,   b < 600 FROM t1;
0|0|1

-- 数字亲和类型将被应用到右边的操作数,将它们从文本转换为整数。然后产生一个数字比较。
SELECT b < '40', b < '60', b < '600' FROM t1;
0|0|1

-- 发生无亲和类型转换。右手边的值都是存储类 INTEGER,它们总是小于左边的 TEXT 值。
SELECT c < 40,   c < 60,   c < 600 FROM t1;
0|0|0

-- 发生无亲和类型转换。值作为 TEXT 进行比较。
SELECT c < '40', c < '60', c < '600' FROM t1;
0|1|1

-- 发生无亲和类型转换。右手边的值都是存储类 INTEGER,它们与左边的 INTEGER 值进行数值比较。
SELECT d < 40,   d < 60,   d < 600 FROM t1;
0|0|1

-- 发生无亲和类型转换。左边的 INTEGER 值总是小于右边的 TEXT 值。
SELECT d < '40', d < '60', d < '600' FROM t1;
1|1|1
  

如果比较被换算,该例中所有的结果都是相同的 - 如果表达式为"a < 40"格式,将被重写为"40 > a"。

4.0 操作符

所有数学运算操作符(+、-、*、/、%、<<、>>、& 和 |)两边的操作数在执行之前都被转换为 NUMERIC 存储类。即使它是有损的和不可逆的,转换都会通过。数学运算操作符中的一个 NULL 操作数,产生一个 NULL 结果。数学运算操作符中的一个操作数看起来不像任何数字或不是 NULL,它将被转换为 0 或 0.0。

5.0 排序、分组和复合的 SELECTs

当查询结果被 ORDER BY 子句进行排序,存储类 NULL 的值将被置顶,其后是穿插的以数字为序 INTEGER 和 REAL 值,再后是以序列进行排序的 TEXT 值,最后是 memcmp() 顺序的 BLOB 值。在排序之前不会发生任何存储类的转换。

当使用 GROUP BY 子句对值进行分组时,不同存储类的值被认为是不同的,除了被认为是相等的 INTEGER 和 REAL 值,如果它们在数值上是相等的话。没有亲和类型会被应用到 GROUP BY 子句的结果中。

复合 SELECT 操作符 UNION、INTERSECT 和 EXCEPT 执行内部的值比较。没有亲和类型被应用到与 UNION、INTERSECT 或 EXCEPT 关联的内部比较操作数上 - 值被直接进行比较。

6.0 校对序列

当 SQLite 比较两个字符串时,如果两个字符串相等,它使用一个校对序列或校对函数来决定哪个字符串更大一些。SQLite 有 3 个内置的校对函数:BINARY、NOCASE 和 RTRIM。

  • BINARY - 使用 memcmp() 对字符串数据进行比较,无论文本编码。
  • NOCASE - 与 BINARY 相同,除了在比较执行之前会将 ASCII 码的 26 个大写字母被折换为与其等值的小写字母。注意,只有 ASCII 码的字符进行大小写折换。由于所需表的大小,SQLite 不会尝试对完整 UTF 的大小写进行折换。
  • RTRIM - 与 BINARY 相同,除了尾随的空格将被忽略。

使用 sqlite3_create_collation() 接口,一个应用程序可以注册附加的校对函数。

6.1 从 SQL 分配校对序列

每个表的每个列都有一个相关联的校对函数。如果没有校对函数被明确定义,校对规则默认为 BINARY。列定义的 COLLATE 子句被用来替代地为一个列定义校对函数。

为一个二元比较操作符(=、<、>、<=、>=、!=、IS 和 IS NOT)决定使用何种校对函数,按照下面展示的规则顺序进行:

  1. 如果两个操作数都使用 COLLATE 后缀操作符分配了一个明确的校对函数,那么明确的校对函数被用在比较中,左边操作数的校对函数有较高的优先级。
  2. 如果两个操作数都是一个列,左边列的校对函数有较高的优先级。前一句的目的是,带有一个或多个一元"+"操作符的列名仍被认为是一个列名。
  3. 否则,比较将会使用 BINARY 校对函数。

表达式"x BETWEEN y AND z"在逻辑上等价于两个比较"x >= y AND x <= z",并且与校对函数一起工作,就像这是有两个分开的比较一样。表达式"x IN (SELECT y ...)"与"x = y"的处理方式一样,目的是为了确定校对序列。用在"x IN (y, z, ...)"格式表达式上的校对序列,就是 x 的校对序列。

ORDER BY 子句是一个 SELECT 语句的一部分,其规则是,可使用 COLLATE 操作符为 SELECT 语句分配一个校对序列,在这种情况下,特定的校对函数被用于排序。否则,如果通过 ORDER BY 子句进行排序的表达式是一个列,列的校对序列将被用来确定排序顺序。如果表达式不是一个列并且没有 COLLATE 子句,则 BINARY 校对序列将被使用。

6.2 校对序列示例

下面的例子用来辨认校对序列,这可被用来确定由各 SQL 语句执行的文本比较的结果。注意,在 NUMERIC、BLOB 或 NULL 值的情况,一个文本的比较并不是必须的,并且不会使用校对序列。

CREATE TABLE t1(
    x INTEGER PRIMARY KEY,
    a,                 /* 校对序列 BINARY */
    b COLLATE BINARY,  /* 校对序列 BINARY */
    c COLLATE RTRIM,   /* 校对序列 RTRIM */
    d COLLATE NOCASE   /* 校对序列 NOCASE */
);
                   /* x   a     b     c       d */
INSERT INTO t1 VALUES(1,'abc','abc', 'abc  ','abc');
INSERT INTO t1 VALUES(2,'abc','abc', 'abc',  'ABC');
INSERT INTO t1 VALUES(3,'abc','abc', 'abc ', 'Abc');
INSERT INTO t1 VALUES(4,'abc','abc ','ABC',  'abc');

/* 使用 BINARY 校对序列执行文本比较 a = b。 */
SELECT x FROM t1 WHERE a = b ORDER BY x;
-- 结果 1 2 3

/* 使用 RTRIM 校对序列执行文本比较 a = b。 */
SELECT x FROM t1 WHERE a = b COLLATE RTRIM ORDER BY x;
-- 结果 1 2 3 4

/* 使用 NOCASE 校对序列执行文本比较 d = a。 */
SELECT x FROM t1 WHERE d = a ORDER BY x;
-- 结果 1 2 3 4

/* 使用 BINARY 校对序列执行文本比较 a = d。 */
SELECT x FROM t1 WHERE a = d ORDER BY x;
-- 结果 1 4

/* 使用 RTRIM 校对序列执行文本比较 'abc' = c。 */
SELECT x FROM t1 WHERE 'abc' = c ORDER BY x;
-- 结果 1 2 3

/* 使用 RTRIM 校对序列执行文本比较 c = 'abc'。 */
SELECT x FROM t1 WHERE c = 'abc' ORDER BY x;
-- 结果 1 2 3

/* 使用 NOCASE 校对序列进行分组(值"abc"、"ABC"和"Abc"被放在相同的分组中)。 */
SELECT count(*) FROM t1 GROUP BY d ORDER BY 1;
-- 结果 4

/* 使用 BINARY 校对序列执行分组。"abc"、"ABC"和"Abc"来自不同的分组。 */
SELECT count(*) FROM t1 GROUP BY (d || '') ORDER BY 1;
-- 结果 1 1 2

/* 使用 RTRIM 校对序列或列 c 执行排序。 */
SELECT x FROM t1 ORDER BY c, x;
-- 结果 4 1 2 3

/* 使用 BINARY 校对序列或 (c || '') 执行排序。 */
SELECT x FROM t1 ORDER BY (c||''), x;
-- 结果 4 2 3 1

/* 使用 NOCASE 校对序列或列 c 执行排序。 */
SELECT x FROM t1 ORDER BY c COLLATE NOCASE, x;
-- 结果 2 4 3 1

添加新评论

相关文章:

  SQLite 对比其它数据库引擎的 NULL 处理

  SQLite 没有实现的 SQL 特征

发自我的 iPhone

阅读SDK示例程序Note的一点笔记

也可以在主程序中使用Intent
intent=getIntent();来设置当前要显示的Activity,这个由AndroidManifest.xml中的下面语句来定义:
<activity android:name="NotesList"
android:label="@string/title_notes_list">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
上面的语句定义默认显示NotesList这个布局。
在调试器中查看intent的值如下所示:
intent Intent (id=830066438464)
mAction "android.intent.action.MAIN" (id=830066438512)
count 26
hashCode -1173447682
offset 0
value (id=830066438544)
mCategories HashSet (id=830066438880)
mComponent ComponentName (id=830066438728)
mData null
mExtras null
mFlags 268435456
mPackage null
mSourceBounds null
mType null
在mAction变量中,保存了要打开的Activity的值(在前所述的文件中定义了)。

我的第一个使用按钮打开另一个Activity的程序

android 按钮打开另一个activity的示例程序
首先,是布局排列问题。一般来说,有经验的用户会选择使用java代码生成界面,但是我对界面代码不太熟悉,所以,我使用了xml文件来生成界面。
打开res->layout,选择main.xml,这是系统默认生成的界面布置xml文件。双击该项,会打开该文件,在页面底部选择layout,出现页面布置页面。在页面上右击鼠标,选择Add菜单项。选择"Button"项,这样就在主界面中加入了一个按钮。
其次要创建一个该按钮打开的activity,也可以理解为打开一个对话框。在Android中,一个Activity由一个java文件和一个xml文件组成。
要创建一个java文件比较简单,单击工具栏中的新建按钮,选择class。在弹出的对话框中,单击"Source
Folder:"后面的"Browse",选择要保存文件的工程名称,一般来说应是当前工程。
在Name编辑框中,输入要创建的java文件名,也就是类名称。如wnAbout.
单击Superclass编辑框后面的"Browse"按钮,选择Activity类。
单击"Finish"按钮结束创建。
这样就创建了一个类。
然后开始创建xml布局文件。
单击工具栏新建按钮,选择Android XML file项。
在弹出的对话框中,单击"Project"后面的"Browse"按钮,选择要创建布局文件的项目。
在File文本框中,输入文件名称。如about.xml。要注意,必须要输入xml这个扩展名。
在"What type of Resource Would you like create?"单选框中,选择Layout项,意思是创建一个布局的xml文件。
在"Select the root element for the XML file"下拉框中,选择LinearLayout项,意思是选择线性布局模式。
单击finish按钮完成创建。

为了让程序可以响应按钮的单击事件,需要建立一个监听器。
现在,单击res->layout,然后双击main.xml项,打开主界面设置页面。单击页面底部的main.xml,直接编辑该xml文件。将其更改成如下内容:
<Button android:text="@string/strAbout"
android:id="@+id/btnAbout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</Button>
意思是让按钮显示字符串strAbout的内容,并且将按钮的id设置为btnAbout。
单击res->values,双击打开strings.xml文件,在其中加入:
<string name="strAbout">about</string>
意思是将strAbout字符串的内容设置为about。
这样,就做好了准备工作。可以单击工具栏的运行按钮或者按"Ctrl+F11"来启动模拟器,并在模拟器中运行该程序。应该可以看到一个问候语字符串和一个显示了About字符的按钮。
现在开始输入代码。
单击src->项目空间名称,双击项目名称为名的java文件。
修改该文件,使其像如下样子:
public class wnReader extends Activity {

private Button btnAbout;//定义一个按钮对象
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

btnAbout=(Button)findViewById(R.id.btnAbout);
btnAbout.setOnClickListener(new View.OnClickListener()//设置监听器
{
public void onClick(View v) {
About();//按钮单击时触发About函数。
}
}); protected void About() {
Intent i = new Intent(this, wnAbout.class);
startActivity(i);
}

}

protected void About()//这个是按钮单击时触发的事件,注意应该定义为protected类型。
{
Intent i = new Intent(this, wnAbout.class);
startActivity(i);
}
现在建立了按钮单击事件的监听器,可以响应该按钮的单击事件。为了让程序可以打开新建的activity,首先需要修改一下AAndroidManifest.xml文件。双击该文件,打开。
在其中加入如下一段内容:
<activity android:name=".wnAbout"
android:label="@string/strAbout">
</activity>
修改后的内容应该如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wnReader"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".wnReader"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name=".wnAbout"
android:label="@string/strAbout">
</activity>

</application>
<uses-sdk android:minSdkVersion="7" />

</manifest>
但是由于系统自动建立的java文件和xml布局文件其实是空白的,所以应该在其上加入一些控件。
单击src->com.wnReader,双击其中的wnAbout.java,打开该文件。修改其内容,修改后内容应该如下所示:
public class wnAbout extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about);//意思是显示名为about.xml的布局文件
}
}
单击res->layout,双击about.xml文件。

我的第一个菜单程序

创建菜单
一般来说,菜单有选项菜单、上下文菜单,以及子菜单。
选项菜单是指程序运行时,按Menu键弹出的菜单,一般来说,一屏最多显示六个菜单项而且参照惯例,应该会给每个菜单项添加图标。而上下文菜单,是指长按某项后出现的菜单。子菜单,顾名思义,就是一个菜单的下级菜单。
创建菜单可以通过代码menu.add来实现。创建菜单应该重写函数onCreateOptionsMenu.使用代码创建菜单的示例如下:
/* Creates the menu items */
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MenuOpenBook, 0, "Open book");
menu.add(0, MenuOption, 0, "Option");
return true;
}

/* 如果要让这些菜单做些工作的话,可以使用如下函数。要注意的是,这些功能都是在重写函数onOptionsItemSelected中实现 */
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {//使用getItemId来获得选中的菜单项。
case MenuOpenBook:
OpenBook();
return true;
case MenuOption:
Option();
return true;
}
return false;
}
如果要让这个菜单在不同的时候有不同的内容,可以重写onPrepareOptionsMenu()函数来实现。该函数在每次菜单被加载时都会运行。
不过,为了方便起见,还是建议使用xml文件来创建菜单。下面来介绍一下使用xml文件创建菜单的方法。
首先,右键单击res项,选择new菜单项,在弹出的级联菜单中选择folder,在Folder
name中输入menu,创建存放菜单文件的目录。这个位置和名称都是不能更改的。必须存放在res目录中,子目录名称必须为menu。
然后,单击工具栏的新建按钮,选择Android xml file。
在File文本框中输入要创建的菜单文件的名称,如menuopenbook.xml。注意,这里的名字一般应该采用小写字母与数字的组合,不应该会采用大写字母。
在"What type of resource would you like to create?"单选框中选择Menu项。意思是创建一个菜单XML文件。
Folder文本框会自动定位到res/menu目录。
单击Finish完成创建。
现在虽然已经创建了一个菜单文件,但其中各项内容还是空白,需要向其中添加内容。
依次单击res->menu->menuopenbook.xml,打开文件准备编辑。
单击页面下方的layout切换到设计视图。
单击Add按钮,在弹出的对话框中选择Create a new element at the top level ,in Menu.意思是创建一个菜单项。
在中间的文本框中输入菜单项的名称。如menuopen。
在列表栏中选择Item项。
单击Ok。
将Id更改为@+id/menuopen,将Title更改为open book。
现在就新建了一个菜单项,id为menuopen,而显示的文字是open book。

打开项目的主文件,wnReader.java,在其中添加代码,将菜单应用到项目中去。
只需要添加如下代码即可:
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menuopenbook, menu);
return true;
}
然后在import区域中添加如下两行:
import android.view.Menu;
import android.view.MenuInflater;
按Ctrl+F11运行程序,在主界面出现时,按模拟器的Menu键,刚才设计的菜单就会从屏幕下方弹出。

Tuesday, July 13, 2010

android学习小结2

文章分类:移动开发
1 在1。5的android中,可以指定edittext中只输入数字,比如可以这样,就弹出小键盘了:
android:inputType="numberDecimal",这样还可以接受输入包含小数点的数字了。
2 读取资源文件中的内容
result.setText(getText(R.String.bmi_result));
注意使用getText函数,读取资源文件中的内容.

3 做一个象"关于我们"的对话框:
new AlertDialog.Builder(Bmi.this)
.setTitle(R.string.about_title)
.setMessage(R.string.about_msg)
.setPositiveButton("确认",
new DialogInterface.OnClickListener(){
public void onClick(
DialogInterface dialoginterface, int i){
}
})
.show();
4 toast组件:显示短的提示消息,过几秒之后就消失:
Toast.makeText(Bmi.this, "关于我们", Toast.LENGTH_SHORT).show();
5 url的打开
new AlertDialog.Builder(Bmi.this)
.setNegativeButton(R.string.homepage_label,
new DialogInterface.OnClickListener(){
public void onClick(
DialogInterface dialoginterface, int i){
//go to url
Uri uri = Uri.parse("http://sites.google.com/site/gasodroid/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
})
.show();
也可以把URI写到资源文件中去,
Uri uri=uri.parase(getString(R.string.homepage_uri));
6 menu菜单
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, MENU_ABOUT, 0, "关于").setIcon(R.drawable.help_browser);
menu.add(0, MENU_Quit, 0, "结束").setIcon(R.drawable.emblem_unreadable);
return super.onCreateOptionsMenu(menu);
}
处理menu的点击动作
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()) {
case MENU_ABOUT:
openOptionsDialog();
break;
case MENU_Quit:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
7 <activity android:name=".Bmi"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>、
这里指出了启动的类是Bmi这个类,,<intent-filter>讲明了这个程序的性质,其中
<action android:name="android.intent.action.MAIN" />讲明了这个BMI是程序的切入点,
<category android:name="android.intent.category.LAUNCHER"
/>讲明这个出现在程序的lanucher列表中
8 intent之间传递数据
Intent intent = new Intent();
intent.setClass(Bmi.this, Report.class);
Bundle bundle = new Bundle();
bundle.putString("KEY_HEIGHT",
field_height.getText().toString());
bundle.putString("KEY_WEIGHT",
field_weight.getText().toString());
intent.putExtras(bundle);
startActivity(intent);
接收信息:
Bundle bunde = this.getIntent().getExtras();
double height = Double.parseDouble(bunde.getString("KEY_HEIGHT"))/100;
9 使用状态拦信息
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;

NotificationManager barManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);

Notification barMsg = new Notification(
R.drawable.icon_128,
"HI�",
System.currentTimeMillis()
);
barMsg.defaults |= Notification.DEFAULT_SOUND;
//barMsg.defaults |= Notification.DEFAULT_ALL;

PendingIntent contentIntent = PendingIntent.getActivity(
this,
0,
new Intent(this, Bmi.class),
PendingIntent.FLAG_UPDATE_CURRENT);

barMsg.setLatestEventInfo(
Report.this,
"HI",
"OK",
contentIntent);

barManager.notify(0, barMsg);
NotificationManager barManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
声明管理器,
Notification barMsg = new Notification(
R.drawable.icon_128,
"HI�",
System.currentTimeMillis()
);
中声明提醒信息,System.currentTimeMillis()表示立刻显示;
barMsg.setLatestEventInfo(
Report.this,
"HI",
"OK",
contentIntent);
这里是添加状态栏的详细信息,这里的"HI"是显示的主题,第三个参数,这里的'OK'是说明,
contentIntent这个参数指明当点状态栏时,相应打开的intent.
10 保存优先级的设置:
private void restorePrefs() {
SharedPreferences settings = getSharedPreferences(PREF, 0);
String pref_height = settings.getString(PREF_HEIGHT, "");

}
这里是找系统中是否以"BMI_PREF"字符串作为文件名的优先级设置的文件,有的话,以settings做为代号来操作
当用户离开activity时,把值进行保存,重写onPause()函数:
super.onPause();
// Save user preferences. use Editor object to make changes.
SharedPreferences settings = getSharedPreferences(PREF, 0);
settings.edit()
.putString(PREF_HEIGHT, field_height.getText().toString())
.commit();
11 多语言界面并存:
比如原来的是英文,则res目录下放values,中文的话,在res目录下再放一个values-zh-rTW
其中zh是主语系,-r是必须的,后面跟分支
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = Locale.TRADITIONAL_CHINESE;
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(conf, dm);
这里是强制使用中文界面,在程序中,针对不同语言提供不同的界面:
if (conf.locale==Local.TRADITIONAL_CHINESE)
12 Spinner下拉菜单中的选择事件:
field_feet.setOnItemSelectedListener(getFeet);
private Spinner.OnItemSelectedListener getFeet = new
Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View v, int
position, long id) {
。。。。。。
}
public void onNothingSelected(AdapterView parent) {
}
};

android学习小结3

文章分类:移动开发
1 activity可以继承扩展 ListActivity
比如:
class DummyNote extends ListActivity {
private String[] note_array = {

"gasolin",
"crota",
"louk",
"magicion"

};
ListAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
note_array);
setListAdapter(adapter);

}
2 使用sqlite
在新建立工程后,打开模拟器后,在sdk的tools下
运行adb shell
cd data/data/
ls
cd 工程名
mkdir databases
cd databases
sqlite3 notes.db (建立了一个notes.db数据库)
create talbe notes
......;
sqlite>.databases (查看当前目录下的数据库列表)
sqllite>.tables (查看所有数据表)
.schema notes (查看指定表的结构)
离开sqllite: .exit

3 CRUD的典型例子
public class NotesDbAdapter {

private static final String DATABASE_NAME = "notes.db";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_TABLE = "notes";
private static final String DATABASE_CREATE =
"create table notes("
+"_id INTEGER PRIMARY KEY,"
+"note TEXT,"
+"created INTEGER,"
+"modified INTEGER"
+");";
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}

private Context mCtx = null;
private DatabaseHelper dbHelper ;
private SQLiteDatabase db;
/** Constructor */
public NotesDbAdapter(Context ctx) {
this.mCtx = ctx;
}
public NotesDbAdapter open () throws SQLException {
dbHelper = new DatabaseHelper(mCtx);
db = dbHelper.getWritableDatabase();
return this;
}
public void close() {
dbHelper.close();
}
//start query
public static final String KEY_ROWID = "_id";
public static final String KEY_NOTE = "note";
public static final String KEY_CREATED = "created";
String[] strCols = new String[] {
KEY_ROWID,
KEY_NOTE,
KEY_CREATED
};
/*
public Cursor getall() {
return db.rawQuery("SELECT * FROM notes", null);
}
*/

/*
// get all entries
public Cursor getall() {
return db.query(DATABASE_TABLE, //Which table to Select
strCols,// Which columns to return
null, // WHERE clause
null, // WHERE arguments
null, // GROUP BY clause
null, // HAVING clause
null //Order-by clause
);
}
*/

// get all entries
public Cursor getall() {
return db.query(DATABASE_TABLE,
new String[] {KEY_ROWID, KEY_NOTE, KEY_CREATED},
null, null, null, null, null);
}
// add an entry
public long create(String Note) {
Date now = new Date();
ContentValues args = new ContentValues();
args.put(KEY_NOTE, Note);
args.put(KEY_CREATED, now.getTime());
return db.insert(DATABASE_TABLE, null, args);
}
//remove an entry
public boolean delete(long rowId) {
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

//query single entry
public Cursor get(long rowId) throws SQLException {
Cursor mCursor = db.query(true,
DATABASE_TABLE,
new String[] {KEY_ROWID, KEY_NOTE, KEY_CREATED},
KEY_ROWID + "=" + rowId,
null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
//update
public boolean update(long rowId, String note) {
ContentValues args = new ContentValues();
args.put(KEY_NOTE, note);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" +
rowId, null) > 0;
}

}
主程序调用:
private NotesDbAdapter mDbHelper;
private Cursor mNotesCursor;

private void setAdapter() {
mDbHelper = new NotesDbAdapter(this);
mDbHelper.open();
fillData();
}
private void fillData() {
mNotesCursor = mDbHelper.getall();
startManagingCursor(mNotesCursor);
String[] from = new String[]{"note"};
int[] to = new int[]{android.R.id.text1};
// Now create a simple cursor adapter
SimpleCursorAdapter adapter =
new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, mNotesCursor,
from, to);
setListAdapter(adapter);
}

新增记录:
public long create(String Note) {
Date now = new Date();
ContentValues args = new ContentValues();
args.put(KEY_NOTE, Note);
。。。。。。
return db.insert(DATABASE_TABLE, null, args);
}
删除记录:
public boolean delete(long rowId) {
return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
mDbHelper.delete(getListView().getSelectedItemId());//这里用getListView().getSelectedItemId()获得选定
删除哪一条记录
查询记录:
//query single entry
public Cursor get(long rowId) throws SQLException {
Cursor mCursor = db.query(true,
DATABASE_TABLE,
new String[] {KEY_ROWID, KEY_NOTE, KEY_CREATED},
KEY_ROWID + "=" + rowId,
null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
更新记录:
//update
public boolean update(long rowId, String note) {
ContentValues args = new ContentValues();
args.put(KEY_NOTE, note);
return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" +
rowId, null) > 0;
}
4 activity中的相关,比如选了A中的记录,然后打开B来编辑,B编辑完后,再返回A。
首先在B中,接收BUNDLE:
private void showViews(Bundle savedInstanceState) {
//mRowId = savedInstanceState != null ?
savedInstanceState.getLong(NotesDbAdapter.KEY_ROWID) :
null;
if (mRowId == null) {
Bundle extras = getIntent().getExtras();
mRowId = extras != null ?
extras.getLong(NotesDbAdapter.KEY_ROWID) : null;
}
//把编辑的数据拿出来
if (mRowId != null) {
Cursor note = mDbHelper.get(mRowId);
startManagingCursor(note);
field_note.setText(note.getString(
note.getColumnIndexOrThrow(NotesDbAdapter.KEY_NOTE)
));
}
当编辑成功提交后,
public void onClick(View view) {
mDbHelper.update(mRowId, field_note.getText().toString());
setResult(RESULT_OK);
finish();
这里的setResult,表示这个activity成功,返回
在调用方中,如果是一个LISTVIEW的列表的话,点某一个列
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, NoteEdit.class);
intent.putExtra(NotesDbAdapter.KEY_ROWID, id);
startActivityForResult(intent, ACTIVITY_EDIT);
}
这里的startActivityForResult表示的是要调用另外一个activity,并且要求结果返回
同时:
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
fillData();
}
5 长按菜单
A 在oncreate函数中,注册
registerForContextMenu(getListView());//说明点listview时会使用长按菜单
B public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.add(0, MENU_DELETE, 0, "删除记事");
menu.setHeaderTitle("要怎么处理这个项目");
super.onCreateContextMenu(menu, v, menuInfo);
}

thanks party ,this post by email.

android学习小结4

文章分类:移动开发

1 用一个VIEW做为消息提示
btn3.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
View view = inflateView(R.layout.view);
TextView txtMsg = (TextView) view.findViewById(R.id.txtMsg);
txtMsg.setText("提示内容");

Toast toast = new Toast(Main.this);
toast.setView(view);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
});
2 状态栏通知
public void onClick(View v) {
// 实例化通知管理器
NotificationManager nm = (NotificationManager) getSystemService

(NOTIFICATION_SERVICE);

// 指定单击通知后所打开的详细的通知页面(单击通知后打开 NotificationView


PendingIntent contentIntent = PendingIntent.getActivity(
Main.this, 0, new Intent(Main.this,

NotificationView.class), 0);

// 实例化一个通知,并指定其图标和标题(在提示栏上显示)
Notification n = new Notification(R.drawable.icon01, "我是滚动的通知信息

我是滚动的通知信息我是滚动的通知信息", System.currentTimeMillis());

// 设置通知的发送人和通知的详细内容(打开提示栏后在通知列表中显示)
n.setLatestEventInfo(Main.this, "通知发送人", "我是详细的通知信息我是详

细的通知信息我是详细的通知信息", contentIntent);

// 100 毫秒延迟后,震动 250 毫秒,暂停 100 毫秒后,再震动 500 毫秒
n.vibrate = new long[] { 100, 250, 100, 500 };

// 发出通知(其中第一个参数为通知标识符)
nm.notify(0, n);
}
});

3 图片按钮:
ImageButton imgButton = (ImageButton) this.findViewById(R.id.imageButton);
// 设置图片按钮的背景
imgButton.setBackgroundResource(R.drawable.icon01);
4 图片显示:
ImageView imgView = (ImageView) this.findViewById(R.id.imageView);
// 指定需要显示的图片
imgView.setBackgroundResource(R.drawable.icon01);
5 checkbox:
CheckBox chk = (CheckBox) this.findViewById(R.id.chk1);
// setOnCheckedChangeListener() - 响应复选框的选中状态改变事件
chk.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
TextView txt = (TextView) _CheckBox.this.findViewById(R.id.textView);
txt.setText("CheckBox01 的选中状态:" + String.valueOf(isChecked));


}
});

6 ToggleButton:
<!--
ToggleButton - 双状态按钮控件
textOn - 当按钮状态为 true 时所显示的文本
textOff - 当按钮状态为 false 时所显示的文本
-->
<ToggleButton android:id="@+id/toggleButton"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textOn="关闭" android:textOff="打开" />

final ToggleButton btn = (ToggleButton)
this.findViewById(R.id.toggleButton);
// setOnClickListener() - 响应按钮的鼠标单击事件
btn.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
TextView txt = (TextView)
_ToggleButton.this.findViewById(R.id.textView);
// ToggleButton.isChecked() - 双状态按钮的按钮状态
txt.setText("按钮状态:" + String.valueOf(btn.isChecked()));
}
});
7 进度条:
<!--
进度条控件(条状)的演示
style - 进度条的样式,本例使用内置样式
max - 进度的最大值
progress - 第一进度位置
secondaryProgress - 第二进度位置
-->
<ProgressBar android:id="@+id/progress_horizontal"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200px"
android:layout_height="wrap_content" android:max="100"
android:progress="50" android:secondaryProgress="75" />

// 设置特性以允许在应用程序的标题栏上显示进度条(条状)
requestWindowFeature(Window.FEATURE_PROGRESS);
// 设置特性以允许在应用程序的标题栏上显示进度条(圆圈状)
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

this.setContentView(R.layout.progressbar);

setTitle("ProgressBar");

// 在标题栏上显示进度条(条状)
setProgressBarVisibility(true);
// 在标题栏上显示进度条(圆圈状)
setProgressBarIndeterminateVisibility(true);

// 指定进度条的进度
setProgress(50 * 100);
setSecondaryProgress(75 * 100);

9 SeekBar:
<!--
SeekBar - 可拖动的进度条控件
max - 进度的最大值
progress - 第一进度位置
secondaryProgress - 第二进度位置
-->
<SeekBar android:id="@+id/seekBar" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:max="100"
android:progress="50" android:secondaryProgress="75" />

mSeekBar = (SeekBar) findViewById(R.id.seekBar);
// setOnSeekBarChangeListener() - 响应拖动进度条事件
mSeekBar.setOnSeekBarChangeListener(this);
// 拖动进度条后,进度发生改变时的回调事件
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromTouch) {
mProgressText.setText(progress + "%");
}

// 拖动进度条前开始跟踪触摸
public void onStartTrackingTouch(SeekBar seekBar) {
mTrackingText.setText("开始跟踪触摸");
}

// 拖动进度条后停止跟踪触摸
public void onStopTrackingTouch(SeekBar seekBar) {
mTrackingText.setText("停止跟踪触摸");
}

10 放大缩小控件:
ZoomControls zoomControls = (ZoomControls)
this.findViewById(R.id.zoomControls);
// setOnZoomInClickListener() - 响应单击放大按钮的事件
zoomControls.setOnZoomInClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(_ZoomControls.this, "单击了放大按钮",

Toast.LENGTH_SHORT).show();
}
});

// setOnZoomOutClickListener() - 响应单击缩小按钮的事件
zoomControls.setOnZoomOutClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(_ZoomControls.this, "单击了缩小按钮",

Toast.LENGTH_SHORT).show();
}
});

11 videoview:
VideoView videoView = (VideoView) findViewById(R.id.videoView);

// 指定需要播放的视频的地址
videoView.setVideoURI(Uri.parse("android.resource://com.webabcd.view/"
+ R.raw.demo));
// videoView.setVideoPath();

// 设置播放器的控制条
videoView.setMediaController(new MediaController(this));
// 开始播放视频
videoView.start();

12 tab控件:
<!-- Tab 1 的内容 -->
<TextView android:id="@+id/view1" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:text="tab1 content" />

<!-- Tab 2 的内容 -->
<TextView android:id="@+id/view2" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:text="tab2 content" />

// 实现 Tab 功能的话要继承 TabActivity
public class _Tab extends TabActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);

TabHost tabHost = getTabHost();
LayoutInflater.from(this).inflate(R.layout.tab,
tabHost.getTabContentView(), true);

// Tab 1 的内容
tabHost.addTab(tabHost.newTabSpec("tab1")
.setIndicator("tab1")
.setContent(R.id.view1));

// Tab 2 的内容(设置了 Tab 图片)
tabHost.addTab(tabHost.newTabSpec("tab2")
.setIndicator("tab2", getResources().getDrawable(R.drawable.icon01))
.setContent(R.id.view2));

// Tab 3 的内容(设置 Tab 的内容为指定的 Activity)
tabHost.addTab(tabHost.newTabSpec("tab3")
.setIndicator("tab3")
.setContent(new Intent(this, _TextView.class)));

}
}

13 GALLERY缩略图组件:
<!--
Gallery - 缩略图浏览器控件
spacing - 缩略图列表中各个缩略图之间的间距
-->
<Gallery android:id="@+id/gallery" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:spacing="20px" />

Gallery gallery = (Gallery) findViewById(R.id.gallery);
// 为缩略图浏览器指定一个适配器
gallery.setAdapter(new ImageAdapter(this));
// 响应 在缩略图列表上选中某个缩略图后的 事件
gallery.setOnItemSelectedListener(new
AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(_Gallery.this,
String.valueOf(position), Toast.LENGTH_SHORT).show();
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {

}
});
}

// 继承 BaseAdapter 用以实现自定义的图片适配器
public class ImageAdapter extends BaseAdapter {

private Context mContext;

public ImageAdapter(Context context) {
mContext = context;
}

public int getCount() {
return mThumbIds.length;
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ImageView image = new ImageView(mContext);

image.setImageResource(mThumbIds[position]);
image.setAdjustViewBounds(true);
image.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

return image;
}
}

// 需要显示的图片集合
private Integer[] mThumbIds = { R.drawable.icon01, R.drawable.icon02,
R.drawable.icon03, R.drawable.icon04, R.drawable.icon05 };

android beginning :button and OnClick

Android 入门到精通 (界面编程#1-从Button说起)
Android 界面编程有两种基本的方法,一种是在代码中,动态创建一个个组件,及把这些组件用Layout来进行组合成复杂的界面展现。一种是用图形化的方式来编写 布局Layout,这些布局被保存在XML文件中,会编译成资源,被程序中的Activity来加载(setContentView()), 再通过findViewById方式来获得每一个界面组件的引用进行操作。对于大多数人来说,喜欢最直观的方式,既代码中动态生成的方式。我们就先从这里说起,至于可视化编程及布局资源的方式以后专门来讲述。
一,布局管理(Layout)
      每一个界面组件都是View的子类,都可以单独占用一个屏幕,但是真正的有用的界面都是这些组件的组合,在Android中都是用各种Layout来进行布局管理,这与传统的J2SE中的一些AWT,SWING界面方式基本相同,这里就不多说。
二,一个单独的界面元素:
     在前面说到Hello World例子中,讲过这样一段代码。在Activity中.
   public class HelloActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText("Hello, World!");
        this.setContentView(tv);
       
    }
}
这里并没有用到Layout,这就是单独的组件方式。也可以改为:
super.onCreate(savedInstanceState);
        Button btn = new Button(this);
        btn.setText("TestButton");
        this.setContentView(btn);
编译运行,会有一个全屏的Button,当然这不是你想要的实用的界面.那我们就用Layout来布局
        super.onCreate(savedInstanceState);
        Button btn = new Button(this);
        btn.setText("TestButton");
        Button btn2 = new Button(this);
        btn2.setText("TestButton2");
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(btn);
        layout.addView(btn2);
        this.setContentView(layout);
编译运行,你就可以看到了两个上下排列的按钮,当然对于布局管理器的使用,做过PC 上AWT,SWING的人都不陌生,这里就不赘述。
       那如何响应事件呢: 大家猜一猜?想必大家不难猜到,在AWT中,在手机的J2ME中,都是用Listener 来处理事件响应,Android也未能脱俗。这与Blackberry,Symbian中的Observer是同一个道理。都是使用了设计模式的观察者模式。下面来看一个能响应事件的例子。

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;


public class HelloActivity extends Activity implements OnClickListener {
  Button btn = null;
  Button btn2 = null;
    public void onClick(View v) {    
  if (v ==  btn)
  {
      this.setTitle("You Clicked Button1");      
  }
  if (v ==  btn2)
  {
      this.setTitle("You Clicked Button2");
  }  
 } 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        btn = new Button(this);
        btn2 = new Button(this);
        btn.setText("TestButton1");        
        btn2.setText("TestButton2");
        btn.setOnClickListener(this);
        btn2.setOnClickListener(this);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(btn);
        layout.addView(btn2);
        this.setContentView(layout);       
    }
}

步骤是:
一,生成两个Button,配置Click事件监听者为HelloActivity ,此类实现了OnClickListener接口。
二,放入布局,按布局显示两个Button
三,按下其中一个Button,生成Click事件,调用HelloActivity 的OnClick接口函数。
四,对于View参数的值,判断是哪个View(Button)。改写Activity的Titile内容。注意,可别去对比View.getId(),缺省情况下,每个组件的Id值都为-1,除非人为设定Id值,用可视化编程时,为自动为其生成一个Id值。