恢复Windows 7 开机密码

2010年06月19日

忘记密码,无法登陆系统,最简单有效的修复办法

1.准备一张Ubuntu安装CD (9.04以上版本)

2.光盘启动,进入Ubuntu安装界面,选择语言后,点击试用(不需要安装)

3.等待加载完毕后,在菜单里选择Mount Windows7的系统分区(具体操作不再细讲)

4.用超级终端进入已Mount的Windows7系统分区目录,找到/Windows/System32目录

5.将目录下osk.exe修改为osk.exe.bak(命令: mv osk.exe osk.exe.bak),并将cmd.exe修改为osk.exe(命令: mv cmd.exe osk.exe)

6.关机并从硬盘启动Windows7

7.出现登录界面后,单击屏幕左下角的”轻松访问”图标,然后在弹出窗口里勾选”启动屏幕键盘”,再单击确定. 此时,就会启动一个DOS命令行窗口(这个命令行窗口,具备超级权限,后续操作就靠它了)

8.在命令行窗口里,输入net user,查看用户名,再输入 net user test newpass,修改用户test的密码为newpass

9.在登录窗口里输入新的密码,就能顺利登录到windows

10.登录成功后,重启计算机并重新进入Ubuntu,还原刚才修改osd.exe和cmd.exe(否则将无法再windows7里使用命令行工具)

备注: 请先掌握Ubuntu或Linux的基础知识,避免误操作.

2009年12月16日

常用刷机命令和方法

1. mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system

2. flash_image recovery /sdcard/recovery.img

3. cat recovery.img > /system/recovery.img

4. fastboot刷机

a) CAMERA+POWER进入手机fastboot模式

b) fastboot erase recovery

c) fastboot flash recovery recovery.img

具体用法就不多说了.

Android G1 刷Recovery简明教程

2009年12月15日

1.SD卡格式化成FAT, 复制DREAIMG.NBH拷到sd卡根目录(RC29或RC7)
2.按照相机 + 开机启动键启动手机, 刷DREAIMG.NBH,成功后重启手机
3.复制recovery.img到sd卡根目录
4.在Home中输入telnetd,启动telnet server
5.通过计算机,输入telnet x.x.x.x 连接手机,如果提示符是#号, 则root成功
6.输入命令 flash_image recovery /sdcard/recovery.img,成功后关机
7.按HOME + 开机启动键启动手机,则自动进入恢复模式.
8.大功告成!

CentOS安装php5.2.X的方法

2009年12月15日

由于centos5.4安装好后通过yum来安装php的版本是5.1.6,现在很多站点都是在5.2.x上开发的,所以我们要添加其他的yum repo来安装Php5.2.x的版本,推荐使用centos 官方的一个test repo里面有php5.2.x

1.添加yum repo php5.2.x 
vi /etc/yum.repos.d/CentOS-Testing.repo 
[c5-testing] 
name=CentOS-5 Testing 
baseurl=http://dev.centos.org/centos/$releasever/testing/$basearch/ 
enabled=1 
gpgcheck=1 
gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
priority=1

2.安装 
yum install php

Ubuntu Linxu安装G1设备驱动方法

2009年07月30日

1.sudo vi /etc/udev/rules.d/50-android.rules
添加内容: SUBSYSTEM==”usb”, SYSFS{”High Tech Computer Corp.”}==”0bb4″, MODE=”0666″

2. sudo vi /etc/udev/rules.d/90-android.rules
添加内容: SUBSYSTEM==”usb”, ATTR{”High Tech Computer Corp.”}==”0bb4″, MODE=”0666″

3.执行一下命令
sudo chmod +x /etc/udev/rules.d/50-android.rules
sudo chmod +x /etc/udev/rules.d/90-android.rules

4. 执行命令: sudo /etc/init.d/udev restart

5.执行命令: sudo killall -9 adb

6.执行命令:sudo adb start-server

建议插入G1时执行第5,6步,直到执行命令 adb devices 能看到手机设备列表时即可。

注意事项:
1. 必须使用sudo及root帐号来执行
2. adb命令应设置好PATH,否则会提示无此命令

HWOTO install and setup Android NDK for Windows(Android NDK 开发环境安装和配置)

2009年06月27日

标 题: HWOTO install and setup Android NDK for Windows
发布日期: 2009-06-27 18:00
原文链接: http://emck.avaw.com/?p=250
作 者: Emck
说 明: 此文档严格遵循GPL协议,转贴请保持此文档的完整性!

1. 下载Android 1.5 NDK, Release 1 For Windows 并解压到D:\android-ndk-1.5_r1

2.下载Cygwin, 执行setup.exe并开始安装(根据网络速度快慢而定, 预计安装需要20分钟左右)
注意:1. 选择台湾的http站点,速度会快很多; 2.开发选项里必须勾选gcc和make,否则后期无法编译

3.执行桌面图标Cygwin,出现linux shell提示符后, 修改当前目录(/home/username)下.bash_profile文件, 加入如下内容在文件尾部
ANDROID_NDK_ROOT=/cygdrive/d/android-ndk-1.5_r1
export ANDROID_NDK_ROOT

4.退出Cygwin,重新进入,执行以下命令
cd $ANDROID_NDK_ROOT
build/host-setup.sh
一切顺利的话会提示设置成功, 如果出错, 则检查错误并修复

5.编译sample hello-jni
进入Cygwin
cd $ANDROID_NDK_ROOT
make APP=hello-jni
一切顺利则会生成libhello-jni.so文件在 $ANDROID_NDK_ROOT/apps/hello-jni/project/libs/armeabi目录下

6.启动预先配置好的Eclipse + ADT环境,创建一个Android Project,选择Create project form existring source
Location = D:\android-ndk-1.5_r1\apps\hello-jni\project, 直接确认即可开始编译并生成apk文件

7.运行这个Project,及可看到效果.

8.祝大家好运

相关资源: Google 讨论组

Android G1 操作技巧,硬启,快捷键,同步联系人,升级rom

2009年03月6日

如何硬启:

方法1:在机器还能正常启动时:

Press Alt+L路径:Menu—Settings—–SD Card and Storage—-Factory Data Reset—-Reset Phone

方法2: 一旦机器死翘翘不能正常启动:

关机,  持续同时按住Home和红键,大约20s,此时机器会启动出现开始屏幕,等看到有个三角警告标示的黑屏时,放手, 滑开键盘,
按下Alt+L,(这个组合键的作用是显示log 文本)
然后,按下 Alt+W 就是  “wipe data /factory reset”, 这个重启的效果是彻底重启,再启动就和刚开箱一样,需要重新绑定google account了。
然后同时按下Home 和返回键,这时候机器应该顺利重启了。 如果此时还不能重启,卸下电池再装上即可。

btw: 还有个命令: Alt+S,应该是执行SD card上的update.zip文件。 这样可以手工升级  (目前G1的升级是通过Tmobile的OTA升级的, 昨天刚刚push了RC19的包,,,但俺这边没反应,应该是不在Tmobile网络里无法OTA的缘故,看来以后要自己手工升级了~~~)

快捷键和操作

全局快捷键启动(默认,可以自己定义修改,search键+任意字母键)quick launch:
Browser SEARCH + b
Contacts SEARCH + c
E-Mail SEARCH + e
Google Mail SEARCH + g
Calendar SEARCH + l
Maps SEARCH + m
Music SEARCH + p
Messaging SEARCH + s
YouTube SEARCH + y
弹出长按菜单:  触屏上选中长按,或是 长按轨迹球

列表中的浏览:Navigation within lists
下翻页 SPACEBAR
上翻页 SHIFT + SPACEBAR
跳转到页尾 ALT + TRACKBALL roll DOWN
跳转到页首 ALT + TRACKBALL roll UP        文本输入和浏览 Typing and text navigation tips:
插入特殊符号 ALT + SPACEBAR opens special character selector
从左起删除 DEL
从右起删除 SHIFT + DEL
删除整行 ALT + DEL
CAPS大写锁定; 双按 SHIFT ,再按取消
光标跳转到首字/尾字 ALT + roll TRACKBALL left/right
制表符 ALT + q
高亮选中文本 SHIFT + roll TRACKBALL
剪切 MENU + x, 或是高亮选中文本后,长按轨迹球,选择弹出菜单中的Cut
复制 MENU + c, 或是高亮选中文本后,长按轨迹球,选择弹出菜单中的Copy
粘贴 MENU + v, 或是高亮选中文本后,长按轨迹球,选择弹出菜单中的Paste
Undo MENU + z
全选  MENU + a, 或是高亮选中文本后,长按轨迹球,选择弹出菜单中的

内置浏览器 Browser shortcuts
Open Go to window MENU + s
Open Bookmarks MENU + b
Open Windows MENU + w
View history MENU + h
Refresh or stop page MENU + r
Go back a page MENU + j
Go forward a page MENU + k
Find on page MENU + f
Go to home page MENU + ENTER
Zoom in MENU + i
Zoom out MENU + o
Go to Settings MENU + p
Page down SPACEBAR
Page up SHIFT + SPACEBAR
————————
GoogleMap shortcuts
Directions MENU + d
Select map mode MENU + m
History MENU + h
My Location MENU + 0 (zero)
Go to Settings MENU + p
Zoom in MENU + i
Zoom out MENU + o
————————-

Gmail:
F – Forward (while viewing message)
R – Reply (while viewing message)
A – Reply All (while viewing message)
Y – Archive (while viewing message or from list)

更多的G1 操作小技巧

通用技巧

1.长按home键会将当前程序置入背景运行

2.调整音量至最低,就会依次进入振动模式和电话铃声静音
3.当然,你也可以长按红键,在菜单里选择静音模式(此时全部静音,包括游戏和音乐)
4.可以在Market里下载一个免费小软,ToggleSetting, 可以一键切换 WiFi开关 GPS开关, 振动模式开关,屏幕超时关闭开关,静音模式开关等,很方便!
5.通过快捷方式在桌面上创建的文件夹,可以通过点击并按住标题栏来重命名,方便归类存放各类快捷方式。(需要安装AnyCut,这个也是must have app!!)
6.长按绿键,自动激活语音拨号, 当然是英文的.
7.可以通过在sdcard里建立诸如 “ringtones”"alarms” “notifications”,然后将铃声文件(ogg,mp3,wav,mid等)放进去,系统的选择声音就可以找到。当然,建议你装一个小软 RingtoneExtended,比这种方法好用!
8.短信可以复制或是转发,在对话模式里选中某条sms后长按即可弹出菜单
9.输入时, 想删除一个词是, 可以menu+del,一次删除一个单位而不是删除一个字母

Chromelite Browser

保存网页上的图片,或是设置为壁纸或是联系人大头贴:

在图片上长按3s, 弹出选择菜单.如果图片后面带着链接的话还有更多选项.

快速滚动:

按住ALT键,再滚动trackball.
按住空格键.
Shift+Space向上滚

其他:

图片上长按trackball激活 “save image/view image”
URL上长按trackball,激活菜单 “open/open in new window/bookmark link/save link/share link/copy link url”
按menu呼出浏览器菜单 (go to url/search/bookmarks/…etc);
快速双击轨迹球,可以激活放大镜模式进行浏览

如何将outlook里的联系人同步到G1

这个问题, 和 “如何将outlook里的联系人同步到Gmail的contacts里“ 是一个问题。

outlook和gmail之间的联系人导入导出, 是通过csv,但是你直接从outlook里导出csv,gamil里直接上载的话, 会发现好多字段映射有问题。。。。(Update: 据说,Outlook里导出csv时选择Dos格式而不是win格式,则可以顺利导入Gmail contacts!而不需要下面的live mail倒腾大法~~~我没验证过,老外说的

我用的最顺利的方法,(适合懒得去分析gmail的csv映射到底哪儿和outlook的有差别了)曲线救国:
1.   登录你的hotmail, 在联系人里,下载一个Windows Live Contacts 导入程序,这个官方程序执行,填入live id,就自动把outlook或是outlook express(可选)的联系人导入到hotmail 联系人里了(嗯嗯,最好有多个hotmail,heh,省的和你本来的msn联系人冲突 )
2.  登录hotmail, 联系人管理里,选择导出csv,
3.  登录gmail, 联系人管理里,选择导入刚刚从hotmail里导出的csv,嗯哪, 大功告成。

此时,如果你的G1设置的是autosync的(缺省就是),那, 看看G1上,contact是不是已经和gmail里的一样了~~

btw: gmail的contact里,是有维护mail的人,才可以加照片~~~~nnd,曾折腾了我好一阵子,怎么有人能加大头照有人就不行~~~

【如何升级Tmobile G1的ROM】

Tmobile G1,发售的机型初始rom版本号为RC19, 目前最新的版本号为RC29,修正了一些问题(fix list参见下面清单)

QUOTE:
Wrong field is focused when keyboard is openend inMessagingapplication: Now when the keyboard is opened, the focus willdefault tothe compose (text entry) field.
Cannot associate withWiFiaccess point using shared WEP key: Should now be able to associatetoaccess points with a shared WEP key.
Google Contacts/Calendar Sync (endless loop).
USBstorage:Now a USB notification will appear in the notifications areawhenconnected via USB. Users must select to use USB Storage ifdesired.
Email notification doesn’t disappear when the Email has been read (POP/IMAP Email client).
New Email notifications not received (POP/IMAP Email client).
Browser does not launch YouTube video when Settings > Enable Javascript is unchecked.
WiFi & Bluetooth occasionally disconnect while charging.
Support silencing of Email notifications (POP/IMAP Email client)
Amazon MP3 fix for files with underscores (_) in the filenames

按Tmobile官方的设计, 一律通过Tmobile通讯网络OTA方式推送升级包。 在Tmobile网络内的G1, 在升级包发布的几天内,都会自动被推送升级包, 用户会看到一个提示框,是否升级,需要重启。确认即可完成升级。很傻瓜化,很不错。

但, 俺们的G1都是在CMCC的网络, 不可能享受到Tmobile的OTA推送。  当然,米国也有很多At&t网络下的G1,没有OTA,照样有勤劳勇敢的劳动人民。。。heh, 下面介绍新鲜火辣的升级指南。

从Tmobile的升级网站下载升级包

将下载好的zip包重命名为update.zip
将update.zip复制到你的microsd 卡的根目录下
长按电源键,关闭G1, 然后,同时按住Home键, 长按红键,启动
一直保持同时长按home和红键的状态,大约20s,当你看到黄色的警告标示符后,正式进入工程模式。

滑开键盘, 按下 ALT-L ,此时显示工程模式的菜单,然后按下 ALT-S 开始刷新rom

等到刷新进度条完成,系统提示你同时按下Home + Back,重启你的机器,在你按下后, 会提示写入radio module, 等一会儿。

系统一会儿会自动重启。 ok,大功告成!  进Settings里的about phone看看, 已经升级完成啦!!!

【Howto】 如何将不断膨胀的浏览器缓存文件移到SDcard上,解决内存紧张问题

感谢sk163 提供的信息来源, 感谢米国网友V_RocKs (Modmygphone上的帖子)

前提:

G1 软件版本必须低于RC30(因为远程登录获得root权限,其实是一个可能有很大隐藏风险的漏洞,google马上发布的RC30更新包将填了这个坑~~~)
你有一张microsd Card,而且有空余空间,而且已经插入G1,而且不是usb mount状态~~~~(有点唐僧啊,)
你已经通过telnetd方式获得了G1的root权限(怎么做,我就不单独介绍了, 本帖里已经有网友转了, 网上搜索G1 越狱,是一坨一坨的文章)

方法:

注: 取得root权限是在pc上的telnet客户端上远程登录后输入命令的, 下面的那些操作,也都是通过telnet方式在pc上操作的。 您别在G1的terminal上操作,heh, 至少现在G1的terminal上还没有sudo这种命令。。
还有, linux是区分大小写的

Android 数据存取之Databases

2009年03月6日

在Android平台上可以操作数据库,这是第一次接触Android时的惊艳之一。在Android平台上,绑定了SQLite数据库,这个数据库系统也是极具性格的,它的最大的应用场景是嵌入式系统,进一步了解可以参看这里

如果有JDBC的经验,那么在这里会容易的多。Android中操作数据库首先要通过一个 类:android.database.sqlite.SQLiteOpenHelper。它封装了如何打开一个数据库,其中当然也包含如果数据库不存在 就创建这样的逻辑。看一个例子:

  1. pubilc class DatabaseHelper extends SQLiteOpenHelper {
  2. private static final String DATABASE_NAME = “com.roiding.simple.note”;
  3. private static final int DATABASE_VERSION = 1;
  4. private static final String NOTES_TABLE_NAME = “notes”;
  5. DatabaseHelper(Context context) {
  6. super(context, DATABASE_NAME, null, DATABASE_VERSION);
  7. }
  8. @Override
  9. public void onCreate(SQLiteDatabase db) {
  10. db.execSQL(“CREATE TABLE ” + NOTES_TABLE_NAME
  11. “ (id integer primary key autoincrement, name text);”);
  12. }
  13. @Override
  14. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  15. db.execSQL(“DROP TABLE IF EXISTS notes”);
  16. onCreate(db);
  17. }
  18. }
pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "com.roiding.simple.note";
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = "notes";

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME
+ " (id integer primary key autoincrement, name text);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}

这里面,如下的语句需要解释:

  • super(context, DATABASE_NAME, null, DATABASE_VERSION)
    数据库连接的初始化,中间的那个null,是一个CursorFactory参数,没有仔细研究这个参数,暂时置空吧。
  • public void onCreate(SQLiteDatabase db)
    这里面的onCreate是指数据库onCreate时,而不是DatabaseHelper的onCreate。也就是说,如果已经指定 database已经存在,那么在重新运行程序的时候,就不会执行这个方法了。要不然,岂不是每次重新启动程序都要重新创建一次数据库了!在这个方法中, 完成了数据库的创建工作。也就是那个execSQL()方法。
  • public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    在程序的开发维护过程中,数据库的结构可能会有变化,那么这个方法就有用处了。在DatabaseHelper这个对象一创建时,就已经把参数 DATABASE_VERSION传入,这样,如果Android发现此版本与现有版本不一致,就会调用这个onUpgrate方法。于是,可以在这里面 实现一些数据的upgrade工作,比如说创建一个临时表,将数据由临时表中转到新的表结构中。需要注意的是,这里面的onUpgrade是在版本不一致 时调用,也就是说不管当前需要的版本高于现有版本还是低于现有版本,都会出发这个方法,类似的这种情况,就需要对oldVersion和 newVersion进行判断之后再决定使用什么策略来更新数据。

在Android中,数据库存放在 /data/data/PACKAGE_NAME/databases 目录下。

接下来就可以使用这个Helper来操作数据库了,操作数据库也就无非是增、删、改、查。先看一个增的例子:

  1. public static void insert(Context context, String s) {
  2. DatabaseHelper mOpenHelper = new DatabaseHelper(context);
  3. String table = “notes”;
  4. String nullColumnHack = “id”;
  5. ContentValues values = new ContentValues();
  6. values.put(“name”, “www.roiding.com”);
  7. long id = mOpenHelper.getReadableDatabase().insert(table,
  8. nullColumnHack, values);
  9. mOpenHelper.getReadableDatabase().close();
  10. }
public static void insert(Context context, String s) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String nullColumnHack = "id";

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

long id = mOpenHelper.getReadableDatabase().insert(table,
nullColumnHack, values);

mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    如果和JDBC例子的话,这一步貌似就像是获得了一个Statement,用它就可以操作数据库了。
  • ContentValues values = new ContentValues();
    Android在向数据库中插入数据的时候,要求数据存放到ContentValues中,这里面的ContentValues其实就是一个 Map,Key值是字段名称,Value值是字段的值。这样,也许你会发现一个问题,那数据类型怎么办?其实在SQLite数据库中就是没有数据类型的, 一切都是字符串。
  • mOpenHelper.getReadableDatabase().insert(table,nullColumnHack, values);
    将数据入库,注意这里面有一个nullColumnHack,看文档是和所有字段都是空的记录有关系,我没有去实验他具体的效果,只是随便给他一个字段名称。

再看一个查的例子:

  1. public static void select(Context context) {
  2. DatabaseHelper mOpenHelper = new DatabaseHelper(context);
  3. String table = “notes”;
  4. String[] columns = new String[] { “id”, “name” };
  5. String selection = “id>? and name<>?”;
  6. String[] selectionArgs = new String[] { “0″, “roiding.com” };
  7. String groupBy = null;
  8. String having = null;
  9. String orderBy = “id desc”;
  10. String limit = “1″;
  11. Cursor c = mOpenHelper.getReadableDatabase().query(table,
  12. columns, selection, selectionArgs, groupBy, having, orderBy, limit);
  13. c.moveToFirst();
  14. for (int i = 0; i < c.getCount(); i++) {
  15. String s = c.getString(1);
  16. c.moveToNext();
  17. }
  18. c.close();
  19. mOpenHelper.getReadableDatabase().close();
  20. }
public static void select(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String[] columns = new String[] { "id", "name" };
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String groupBy = null;
String having = null;
String orderBy = "id desc";
String limit = "1";

Cursor c = mOpenHelper.getReadableDatabase().query(table,
columns, selection, selectionArgs, groupBy, having, orderBy, limit);

c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
String s = c.getString(1);
c.moveToNext();
}
c.close();
mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    于前文中的相同
  • mOpenHelper.getReadableDatabase().query();
    通过mOpenHelper.getReadableDatabase(),会得到一个SQLiteDatabase类型的只读的数据库连接,在这里直接调用了他的query方法。这个query方法相对复杂,因为他将一个完整的SQL语句拆成了若干个部分:

    • table:表名。相当于SQL的from后面的部分。那如果是多表联合查询怎么办?那就用逗号将两个表名分开,拼成一个字符串作为table的值。
    • columns:要查询出来的列名。相当于SQL的select后面的部分。
    • selection:查询条件,相当于SQL的where后面的部分,在这个语句中允许使用“?”,也就是说这个用法和JDBC中的PreparedStatement的用法相似。
    • selectionArgs:对应于selection的值,selection有几个问号,这里就得用几个值。两者必须一致,否则就会有异常。
    • groupBy:相当于SQL的group by后面的部分
    • having:相当于SQL的having后面的部分
    • orderBy:相当于SQL的order by后面的部分,如果是倒序,或者是联合排序,可以写成类似这样:String orderBy = “id desc, name”;
    • limit:指定结果集的大小,它和Mysql的limit用法不太一样,mysql可以指定从多少行开始之后取多少条,例如“limit 100,10”,但是这里只支持一个数值。
  • c.moveToFirst();
    这一句也比较重要,如果读取数据之前,没有这一句,会有异常。
  • c.getString(1);
    与JDBC一致了,Android不支持按字段名来取值,只能用序号。

再看一个删除和修改的例子:

  1. public static void delete(Context context) {
  2. DatabaseHelper mOpenHelper = new DatabaseHelper(context);
  3. String table = “notes”;
  4. String selection = “id>? and name<>?”;
  5. String[] selectionArgs = new String[] { “0″, “roiding.com” };
  6. String whereClause = selection;
  7. String[] whereArgs = selectionArgs;
  8. mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
  9. mOpenHelper.getWritableDatabase().close();
  10. }
public static void delete(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

有了上面的基础这里就容易理解了,这里的whereClause相当于前面的selection,whereArgs相当于前面的selectionArgs。

  1. public static void update(Context context) {
  2. DatabaseHelper mOpenHelper = new DatabaseHelper(context);
  3. String table = “notes”;
  4. String selection = “id>? and name<>?”;
  5. String[] selectionArgs = new String[] { “0″, “roiding.com” };
  6. String whereClause = selection;
  7. String[] whereArgs = selectionArgs;
  8. ContentValues values = new ContentValues();
  9. values.put(“name”, “www.roiding.com”);
  10. mOpenHelper.getWritableDatabase().update(table, values,
  11. whereClause, whereArgs);
  12. mOpenHelper.getWritableDatabase().close();
  13. }
public static void update(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

mOpenHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

这个update的用法,综合select和delete就可以理解。

注意:

  • Cursor和Databases要及时关闭,不然也会有异常。
  • getWritableDatabase()和getReadableDatabase()在当前的Android版本中貌似可以通用,像上面的insert,用的就是getReadableDatabase。

在真实的应用中,会对上面这些基本操作做更高一级的抽象和封装,使之更容易使用。在select时,除了用上述的方法,将分段的SQL语句传进去之 外,Android还支持一种方法:使用SQLiteQueryBuilder。如果使用的是上述的分段SQL语句的方法,在Android的内部实现 中,也是先将分段的SQL使用SQLiteQueryBuilder的静态方法来生成一个真正的SQL的,而且,我没有看出来使用 SQLiteQueryBuilder的优势。

Android 数据存取之Files

2009年03月6日

如同前面说的使用Preferences一样,使用File来读写文件也属于常规思路。在Android中没有提供像J2SE里面多的让人抓狂的有关于IO的API。所以使用起来非常简单轻巧。

在Android系统中,这些文件保存在 /data/data/PACKAGE_NAME/files 目录下。

数据读取

  1. public static String read(Context context, String file) {
  2. String data = “”;
  3. try {
  4. FileInputStream stream = context.openFileInput(file);
  5. StringBuffer sb = new StringBuffer();
  6. int c;
  7. while ((c = stream.read()) != -1) {
  8. sb.append((char) c);
  9. }
  10. stream.close();
  11. data = sb.toString();
  12. catch (FileNotFoundException e) {
  13. catch (IOException e) {
  14. }
  15. return data;
  16. }
public static String read(Context context, String file) {
String data = "";
try {
FileInputStream stream = context.openFileInput(file);
StringBuffer sb = new StringBuffer();
int c;
while ((c = stream.read()) != -1) {
sb.append((char) c);
}
stream.close();
data = sb.toString();

} catch (FileNotFoundException e) {
} catch (IOException e) {
}
return data;
}

从代码上,看起来唯一的不同就是文件的打开方式了: context.openFileInput(file); Android中的文件读写具有权限控制,所以使用context(Activity的父类)来打开文件,文件在相同的Package中共享。这里的 Package的概念同Preferences中所述的Package,不同于Java中的Package。

数据写入

  1. public static void write(Context context, String file, String msg) {
  2. try {
  3. FileOutputStream stream = context.openFileOutput(file,
  4. Context.MODE_WORLD_WRITEABLE);
  5. stream.write(msg.getBytes());
  6. stream.flush();
  7. stream.close();
  8. catch (FileNotFoundException e) {
  9. catch (IOException e) {
  10. }
  11. }
public static void write(Context context, String file, String msg) {
try {
FileOutputStream stream = context.openFileOutput(file,
Context.MODE_WORLD_WRITEABLE);
stream.write(msg.getBytes());
stream.flush();
stream.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
}

在这里打开文件的时候,声明了文件打开的方式。

一般来说,直接使用文件可能不太好用,尤其是,我们想要存放一些琐碎的数据,那么要生成一些琐碎的文件,或者在同一文件中定义一下格式。其实也可以将其包装成Properties来使用:

  1. public static Properties load(Context context, String file) {
  2. Properties properties = new Properties();
  3. try {
  4. FileInputStream stream = context.openFileInput(file);
  5. properties.load(stream);
  6. catch (FileNotFoundException e) {
  7. catch (IOException e) {
  8. }
  9. return properties;
  10. }
  11. public static void store(Context context, String file, Properties properties) {
  12. try {
  13. FileOutputStream stream = context.openFileOutput(file,
  14. Context.MODE_WORLD_WRITEABLE);
  15. properties.store(stream, “”);
  16. catch (FileNotFoundException e) {
  17. catch (IOException e) {
  18. }
  19. }

Android数据存取之Preferences

2009年03月6日

这种方式应该是用起来最简单的Android读写外部数据的方法了。他的用法基本上和 J2SE(java.util.prefs.Preferences)中的用法一样,以一种简单、 透明的方式来保存一些用户个性化设置的字体、颜色、位置等参数信息。一般的应用程序都会提供“设置”或者“首选项”的这样的界面,那么这些设置最后就可以 通过Preferences来保存,而程序员不需要知道它到底以什么形式保存的,保存在了什么地方。当然,如果你愿意保存其他的东西,也没有什么限制。只 是在性能上不知道会有什么问题。

在Android系统中,这些信息以XML文件的形式保存在 /data/data/PACKAGE_NAME/shared_prefs 目录下。

数据读取

  1. String PREFS_NAME = “Note.sample.roiding.com”;
  2. SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
  3. boolean silent = settings.getBoolean(“silentMode”, false);
  4. String hello = settings.getString(“hello”, “Hi”);
String PREFS_NAME = "Note.sample.roiding.com";
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean silent = settings.getBoolean("silentMode", false);
String hello = settings.getString("hello", "Hi");
这段代码中:
  • SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    通过名称,得到一个SharedPreferences,顾名思义,这个Preferences是共享的,共享的范围据现在同一个Package中,这里 面说所的Package和Java里面的那个Package不同,貌似这里面的Package是指在AndroidManifest.xml文件中:

    1. <manifest xmlns:android=“http://schemas.android.com/apk/res/android”
    2. package=“com.roiding.sample.note”
    3. android:versionCode=“1″
    4. android:versionName=“1.0.0″>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.roiding.sample.note"
    android:versionCode="1"
    android:versionName="1.0.0">

    这里面的package。根据我目前的实验结果看,是这样的,欢迎指正。后面的那个int是用来声明读写模式,先不管那么多了,暂时就知道设为0(android.content.Context.MODE_PRIVATE)就可以了。

  • boolean silent = settings.getBoolean(”silentMode”, false);
    获得一个boolean值,这里就会看到用Preferences的好处了:可以提供一个缺省值。也就是说如果Preference中不存在这个值的话,那么就用后面的值作为返回指,这样就省去了我们的if什么什么为空的判断。

数据写入

  1. String PREFS_NAME = “Note.sample.roiding.com”;
  2. SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
  3. SharedPreferences.Editor editor = settings.edit();
  4. editor.putBoolean(“silentMode”, true);
  5. editor.putString(“hello”, “Hello~”);
  6. editor.commit();
String PREFS_NAME = "Note.sample.roiding.com";
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("silentMode", true);
editor.putString("hello", "Hello~");
editor.commit();

有了上面数据读取的代码,这里面的就容易理解了,只是别忘了最后的commit();