目录
一. Android 调试
1.Android 调试的主要组件
- Android 调试桥 (ADB)
- Dalvik 调试监视服务 (DDMS)
- 设备 / AVD
- JDWP 调试器
- 除了主调试工具,还可以使用以下工具来调试和配置应用:
- Hierarchy Viewer
- Traceview
2.生成、检查日志
- Android 提供 LogCat类 监视应用程序的日志输出,通过 ADB / DDMS 读取实时消息
- 日志内容:
- 仿真器引发错误时的堆栈跟踪
- 通过使用 android.util 包的 Log类方法 从应用程序打印消息
- Android系统生成的消息
- 日志严重性级别按 降序 排列依次为:
- 错误 error :Log.e(String tag, String msg)
- 警告 wanring :Log.w()
- 信息性消息 info :Log.i()
- 调试消息 debug :Log.d()
- 详细信息 verbose::Log.v()
3.从带有 ADT插件 的 Eclipse 中调试应用
3.1 Debug透视图
- 提供 进入或跨过 方法调用 和 窥视变量以检查其值的功能
3.2 DDMS透视图
- 提供用于为调试选择各个过程的工具
3.3 ADB 安卓调试桥
- Android Debug Bridge:充当开发硬件 和 设备/仿真器 之间的通信媒介
- 一般最多允许同时存在 16个 运行虚拟机,指定 des 确定连接哪个虚拟机运行
- ADB命令用法:adb [-d|-e|-s <serial number>] <command>
- -d:指示命令到已连接的 USB 设备
- -e:指示命令到正在运行的设备
- -s<serial number>:指示命令到具有给定序列号的 USB 设备或仿真器
- 常见ADB命令:
命令
描述
devices
生成已连接的仿真器/设备列表。
序列号 + 状态(脱机/设备)
get-serialno
打印已连接的设备序列号字符串。
get-state
打印仿真器/设备实例的 ADB 状态。
install <path-to-apk>
在仿真器/设备上安装 Android 应用程序(指定为到 .apk 文件的完整路径)。
kill-server
终止 ADB 服务器进程。
logcat [<option>] [<filter-specs>]
将日志数据打印到屏幕。
pull <remote> <local>
将指定文件从仿真器/设备实例复制到您的计算机。
ADB shell 可以执行的命令:
push <local> <remote>
将指定文件从您的计算机复制到仿真器/设备实例。
Shell or shell [<shellCommand>]
在目标仿真器/备实例中启动远程 shell,或在目标仿真器/设备中发出 shell 命令。
Example:adb [-d|-e|-s {<serialNumber>}] shell
start-server
检查 ADB 服务器进程是否正在运行,如果没有运行,启动该服务器进程。
Shell 命令
描述
dumpsys
将系统数据转储到屏幕。
dumpstate
将状态转储到文件。
logcat [<option>]... [<filter-spec>]...
启用无线日志记录并将输出打印到屏幕。
dmesg
将内核调试消息打印到屏幕。
start
启动(重新启动)仿真器/设备实例。
stop
停止执行仿真器/设备实例。
二.SQLite
1.数据存储机制
- SQLite 数据库 (SQLite Database):存储大量数据,需要关系型数据库来管理数据
- 内部存储器 (Internal Storage):数据量小,且很少更改,文件属于应用私有
- 外部存储器 (External Storage):对内部存储器的扩充,存入的文件可以被所有应用访问
- 共享首选项 (Shared Preferences):存储原生数据类型的键值对,是快速存储默认值、用户偏好设置的理想方法
- 网络连接 (Internet Connection):使用能够访问远程位置的数据
2.SQLite数据库
- 自给自足的、无服务器的、零配置的、事务性的、开源的、轻量级的SQL数据库引擎
- 目的:2000年,D.Richard.Hipp为了 不需要管理即可操作程序 而设计了SQLite
- SQLite数据库 特点:
- 自足自给的:不需要任何外部依赖
- 无服务器的:不需要单独的服务器或操作系统
- 零配置的:不需要安装或管理
- 事务性的:完全兼容ACID,允许从多个进程安全访问
- 轻量级的:完全配置时小于400KB,省略可选功能配置小于250KB
- SQLite数据库 数据类型:
3.使用 SQLite 的两种方式
- SQLite数据库 存储位置: /data/data/<package_name>/databases 文件夹
- 默认情况下,所有数据库私有,仅供创建它们的应用访问
- 创建 SQLite数据库时,应考虑因素:
- 图像、音频文件不应存储在数据库中
- 所有表应包括一个自动递增的键字段,即唯一索引值
- 创建数据库,有两种方式:
- 使用 SQLite工具,Linux shell (复杂 用得少)
- 通过 Java代码 编程
4.使用 ADB工具shell 操纵SQLite
- ADB工具:
- 在执行ADB shell命令之前,必须开启AVD(虚拟机),否则会报错 not found
- shell 命令总结:
- adb shell:进入adb shell
- mkdir /data/data/com.Lyrelion.log/databases :创建数据库目录结构
- cd /data/data/com.Lyrelion.log/databases :进入数据库目录结构
- sqlite3 ww :创建数据ww
- .databases :查看所有数据库
- create table t_user (id integer primary key ,name text,pwd name):创建表t_user
- .tables:查看所有表
- insert into t_user values (1,“andy”,“123456”):插入信息
- select * from t_user:查看信息
- exit:退出
5.通过 Java代码 操纵SQLite
5.1 创建SQLite 相关类
- SQLiteDatabase类:公开方法实现数据库增删改查,如:insert(),update(),delete(),query(),execSQL()
- SQLiteOpenHelper类:用于创建和管理数据库,包括数据库版本管理
- Cursor接口:查询返回的结果集
- ContentValues类:一个该类对象表示一行数据
- SQLiteQueryBuilder类:提供方法从SQLite数据库中检索数据
- SQLiteStatement类:实现预编译功能
5.2 SQLiteDatabase 类
- 创建和删除数据库、对数据库执行 SQL命令及其他数据库管理方法,提供以下方法:
- close():关闭数据库
- execSQL(String sql):一个此方法仅能输入一条sql语句,一旦创建了数据库,可执行此方法在数据库中创建表
- getPath() / getVersion():获取路径 / 版本号
- isOpen() / isReadOnly() :判断是否打开 / 是否只读
5.3 SQLiteOpenHelper 类
- 创建数据库的首选方法,此类是抽象类,用于创建、打开和升级数据库,有以下回调方法:
- onCreate(SQLiteDatabase db):方法比较鸡肋,创建数据库的同时才能创建表,创建过数据库再建表会失败
- onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):更改数据库旧版本至新版本
- onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
- onOpen(SQLiteDatabase db):打开数据库
- SQLiteOpenHelper 类提供的其他一些方法有:close() getWritableDatabase() getReadableDatabase()
5.4 Cursor接口
- 返回结果集,提供以下方法:
method
description
args
moveToPosition(int position)
将光标移动到结果集中的指定行
position:指定移动的位置
moveToFirst()
将光标移动到结果集中的第一行
moveToNext()
将光标移动到结果集中的下一行
moveToLast()
将光标移动到结果集中的最后行
moveToPrevious()
将光标移动到结果集中的前一行
getCount()
返回结果集存在的行数
getColumnIndex(String columnName)
返回给定列名的基于零的索引或-1(指定列不存在)
columnName:指定目标列的名称
getColumnIndexOrThrow()
返回给定列名的索引(指定列不存在引发异常)
getColumnName(int columnIndex)
返回给定列索引的名称
columnIndex:指定目标列的索引
getColumnNames()
返回字符串数组,由结果集中的所有列的名称组成
5.5 SQLiteStatement类
- 实现预编译功能,提供以下方法:
- execute()
- executeInsert()
- executeUpdateDelete()
5.6 SQLiteQueryBuilder类
- 检索数据,提供以下方法:
- setTables(String tables)
- appendWhere(CharSeqyence inWhere)
- query(SQLiteDatabase db,String[] columns,String selections,String[] selectionArgs,String groupBy,String having,String sortOdert)
6.登录注册交互实例
- 书写 登录 activity_main.xml、注册 activity_register.xml、成功登录 activity_success.xml 的布局页面
- 创建 数据库及表 相关文件:MyDBOpenHelper.java
- 书写 登录 MainActivity.java、注册 RegisterActivity.java、登陆成功 SuccessActivity.java 的活动界面
- 登录活动界面逻辑:声明并创建数据库对象 获取布局组件对象 设置登录按钮点击监听事件(判断是否输入:未输入就提示,输入就执行数据库查询操作 判断库中是否有对应数据,若有则登录成功,若没有则跳转注册界面) 书写数据库查询的方法
- ⑤注册活动页面逻辑:声明并创建数据库对象 获取布局组件对象 设置提交按钮点击监听事件(判断是否输入:未输入就提示,输入就执行数据库插入操作 然后跳转到登录界面) 书写数据库插入的方法
- 布局文件代码展示:
<!-- activity_main.xml 登录布局界面 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" ... android:orientation="vertical" // 线性垂直布局 tools:context=".MainActivity" > // 登录布局页面 和 登录活动界面关联 <EditText android:id="@+id/admin" android:drawableLeft="@drawable/admin" // 插入图标 android:hint="请输入用户名:" // 文本提示信息 /> <EditText android:id="@+id/password" ... /> <Button android:id="@+id/login" ... android:layout_gravity="center" // 按钮居中对齐 android:layout_marginTop="30dp" // 调整按钮外边距 android:text="Login"/> </LinearLayout> <!-- activity_register.xml 注册布局界面 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ... android:orientation="vertical" // 线性垂直布局 tools:context=".RegisterActivity" > // 注册布局界面 和 注册活动界面关联 <EditText android:id="@+id/admin" android:drawableLeft="@drawable/admin" android:hint="请输入用户名:" /> <EditText android:id="@+id/password" .../> <Button android:id="@+id/register" .../> </LinearLayout> <!-- activity_success.xml 登录成功布局界面 --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" // 相对布局 ... tools:context=".SuccessActivity" > // 登录成功布局界面 和 登录成功活动界面关联 <TextView ... android:text="恭喜你登录成功!" /> </RelativeLayout>
- 创建数据库及表 MyDBOpenHelper.java 代码展示:
public class MyDBOpenHelper extends SQLiteOpenHelper { //1:创建数据库的 SQL命令,被存储在变量 CREATE_TABLE_SQL中,下面调用此变量 final String CREATE_TABLE_SQL="create table t_admin (id integer primary key,name text,password text);"; public MyDBOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, null, version); // 第三个参数 factory不存在,要赋值null,然后打印日志 Log.w("SQLite", "构造函数 MyDBOpenHelper()初始化"); } @Override // 下面的方法比较鸡肋 只有在创建数据库的同时才能创建表 创建过数据库再创建表会失败 public void onCreate(SQLiteDatabase db) { // 首次创建数据库时调用 onCreate() //2:创建数据库表 db.execSQL(数据库语句 仅能写一条 这里写了变量名 在上面定义具体语句) db.execSQL(CREATE_TABLE_SQL); Log.w("SQLite", "onCreate()方法创建数据库t_admin"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w("SQLite", "onUpgrade()方法更改数据库旧版本"+oldVersion+"至新版本"+newVersion); } @Override public void onOpen(SQLiteDatabase db) { Log.w("SQLite", "onOpen()方法打开了数据库"+db.getVersion()); super.onOpen(db); }}
- 登录活动界面 MainActivity.java 代码展示:
public class MainActivity extends Activity { private MyDBOpenHelper myDbOpenhelper; // 声明 MyDBOpenHelper 对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 创建 MyDBOpenHelper对象 创建数据库名admin 内容为空 版本号是1 myDbOpenhelper = new MyDBOpenHelper(MainActivity.this, "admin", null, 1); // 1:获取组件对象 对象名见名知意 final EditText adminEditText = (EditText) findViewById(R.id.admin); final EditText passwordEditText = (EditText) findViewById(R.id.password); final Button loginButton = (Button) findViewById(R.id.login); // 2:设置 button按钮点击事件监听 先写最终的分号保证代码正确性 loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 2.1:获取用户输入的信息 此处会提示将上面的 adminEditText 改成 final类型 // 强制转化成 String数据类型原因:下面方法用 String类型 否则报错 String name = adminEditText.getText().toString(); String password = passwordEditText.getText().toString(); // 3:判断用户是否输入账号密码 if ("".equals(name)&&"".equals(password)) { // 如果没有输入账号密码 弹出对话框提示 记得别忘记show() Toast.makeText(MainActivity.this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); }else{ // 如果输入了账号密码 调用查询方法 if(selectData(myDbOpenhelper.getReadableDatabase(),name,password)) { // 查询到账号密码了 则跳转显示成功登录界面 Intent intent = new Intent(MainActivity.this,SuccessActivity.class); startActivity(intent); }else { // 未查询到账号密码 则跳转到注册界面 Intent intent = new Intent(MainActivity.this, RegisterActivity.class); startActivity(intent); }}}});} // 查询需要的对象 这是自定义查询方法 上面会调用这个方法 如查询名字 密码 public Boolean selectData(SQLiteDatabase db,String name,String password){ Boolean mark = false; // 没查询到结果,返回false // Cursor接口 返回数据结果集 Cursor cursor = db.query("t_admin", null, "name=?and password=?", new String[]{name,password}, null, null, null); if (cursor.moveToNext()) { // 查询到结果 并打印日志 Log.w("SQLite","用户名:"+ cursor.getString(1)); Log.w("SQLite","密码:"+cursor.getString(2)); mark = true; } return mark; }}
- 注册活动界面 RegisterActivity.java 代码展示:
public class RegisterActivity extends Activity { private MyDBOpenHelper dbOpenHelper ; // 定义 MyDBOpenHelper对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); dbOpenHelper = new MyDBOpenHelper(RegisterActivity.this, "admin", null, 1); final EditText adminEdit = (EditText) findViewById(R.id.admin); final EditText passwordEdit = (EditText) findViewById(R.id.password); final Button registerButton = (Button) findViewById(R.id.register); registerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 获取用户输入的信息 String name = adminEdit.getText().toString(); String password = passwordEdit.getText().toString(); // 判断用户是否输入了账号密码 if ("".equals(name)||"".equals(password)) { Toast.makeText(RegisterActivity.this, "用户名或密码不能为空!", Toast.LENGTH_SHORT).show(); }else { // 若用户输入了账户密码 执行 insertData()方法插入数据 insertData(dbOpenHelper.getReadableDatabase(), name, password); Intent intent = new Intent(RegisterActivity.this, MainActivity.class); startActivity(intent); }}});} // 创建insertData()方法 实现插入数据 public void insertData(SQLiteDatabase database,String name,String password){ ContentValues values = new ContentValues(); // 一个 ContentValues类 表示一行数据 values.put("name", name); // values.put:放入键值对 values.put("password", password); database.insert("t_admin", null, values); // 将上述数据执行插入 }}
- 运行后日志打印展示:
7.SQLite 小结
- SQLite 是一个 RDBMS,ADB允许用户直接从 shell命令行 或 Java脚本 操纵数据库
- Android 提供各种方法 存储检索应用数据,即:SQLite、内部存储器、外部存储器、共享首选项和网络连接
- SQLiteDatabase类公开用于管理 SQLite 数据库的各种方法
- SQLiteDatabase类提供 openOrCreateDatabase() 方法来打开现有数据库或创建新数据库(如果不存在)
- SQLiteOpenHelper类是抽象类,用于创建、打开和升级数据库,并管理数据库版本