老黎android笔记1

1. eclipse 可以找到其它的view,如File Explorer, Emulator Control等


2.
通过 adb 安装软件到模拟器 adb install c:\aaa.apk
卸载:adb uninstall <应用程序包名>


.java-->.class-->.dex--->打包(签名) (缺省的密钥文件在 Preference->android中设置)


其它用 dip(dp) 文字用 sp


HVGA: 320*480 标准屏幕


3.
如何得到源代码并在Eclipse中配置?
源码很大,需要使用git工具下载,具体请参考官方文档;
对于开发者来说比较重要的源码包括:1. android api 的所有实现  2. 手机自带程序实现
这些源码分别可以在 frameworks\base 和 package\apps 中找到,我这里是这样做的:
(1) 在对应平台下(如 android-8) 新建 sources 目录,在此目录中新建 base 和 package两个文件夹 (文件夹名子可以随意取), 然后把 android.*.* 的所有源码放到 base 目录(只需要去frameworks\base 下面寻找 android\*\* 这样的文件夹就行,不过似乎直接放到目录下也是可以行的)
(2) 把各应用的源代码放到 package 包内就行了
(3) Eclipse 会自动关联源码(好奇怪),即使不自动关联手动设置下(设置方法:在库上右键-属性)

我的源代码设置如下图:




4.
让模拟器拨号,查看源代码(使用Intent,设置其action,catalogue,data信息来启动一个Activity)
参考代码如下:

String number = editPhoneNum.getText().toString();
Intent intent = new Intent("android.intent.action.CALL");
intent.setData(Uri.parse("tel:" + number));
startActivity(intent); //startActivity(int) 时会默认传递一个android.intent.category.DEFAULT,所以不需要在 intent中再指定
5.
连接手机时用 screenMonitor进行手机屏幕在电脑屏幕上检测

6.
系统自带打电话软件的名字是:Phone


7.
当使用 EidtText时,如果想行数多点可以使用 minLines = 3 来增加行


8.
发短信: 

String number = editPhoneNumber.getText().toString();
String content = editSmsContent.getText().toString();
SmsManager sm = SmsManager.getDefault();
ArrayList<String> msgs = sm.divideMessage(content);
for(String msg : msgs) {
	//最后两个参数:倒数第二个用来指示短信是否发短成功,倒数第一个指示对方是否成功接收短信,可能不准确,具体看文档
	//后两个参数是异步形式的
	sm.sendTextMessage(number, null, msg, null, null); 
}
Toast.makeText(MainActivity.this, "短信发送成功", Toast.LENGTH_SHORT).show();

短信权限: SEND_SMS

9.
Ctrl + f12 切换模拟器屏幕方向 或者 Ctrl+F11 ?


10.
单元测试(首先在manifest.xml文件中配置,然后集成 AndroidTestCase 编写测试工作,可以直接新建测试项目,这时候manifest.xml为测试的配置已经配置好)
集成测试环境的一个manifest.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.sendmessage.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.example.sendmessage" 
        />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <uses-library android:name="android.test.runner" />
    </application>

</manifest>

11.
android api 分类


android.drm 在哪? 不在base里 在frameworks\base\drm中
android.graphics 在哪?在frameworks\base\graphics中
android.location 在哪?frameworks\base\location中
android.media (android.media/android.media.audiofx/android.media.effect)在哪?在frameworks\base\media中
android.nfc 在哪?
android.opengl 在哪?在frameworks\base\opengl
android.renderscript在哪?
android.sax在哪?frameworks/base/sax 下面
android.security 在哪?
android.telephony 在哪? 在\frameworks\base\telephony中


12. 
如何获得老的 android 参考文档?
如果使用 SDK Manager.exe 来下载东西,可以发现它只包含了最新的 android doc ,而有时候我们需要老的 android doc,比哪我们正在学习android2.2,如果我们使用android3.0文档就会让我们很迷惑。下面是一个答案:
The solution on how to get an older documentation version: http://dl-ssl.google.com/android/repository/repository.xml contains the filenames used by the sdk installer (for the SDK itself all filenames, even older ones, are included, but for the documentation only the latest filename is included). You just need to understand the naming pattern, for the docs it looks like docs-2.0_r01-linux.zip (note that even on windows the docs file is the linux named one!). Just append it to the url instead of repository.xml: http://dl-ssl.google.com/android/repository/docs-2.0_r01-linux.zip gives you the docs for 2.0 and http://dl-ssl.google.com/android/repository/docs-2.2_r01-linux.zip for 2.2 :-) When browsing the documentation, make sure not to use the search function, this will lead you to the (updated) onlien version!
总体意思是:http://dl-ssl.google.com/android/repository/repository.xml文件中没有列出老的文档,因此通过 SDK Manager.exe我们下载不到。如果想要下载只能自己指定资源,如http://dl-ssl.google.com/android/repository/docs-2.2_r01-linux.zip 来下载 android2.2资源。因为是HTML文档,所以Windows平台也可以使用这个资源。


13.
调用 adb devices 是只显示: error
经过查博客,找到如下解决方案:
重新安装adb 驱动。


解决方法:
adb kill-server


adb start-server


adb remount


再使用adb devices和adb shell就可以使用android adb功能了。


14. android数据的存储与读取
文件/SharedPreference/SQLite/ContentProvider/网络


文件存取:
自带存储空间(类似电脑硬盘,不要存储大文件)/外部存储设备(类似U盘)
内部空间文件读取:

public class FileService {
	
	private Context context;
	
	public FileService(Context context) {
		this.context = context;
	}
	public void save(String fileName, String fileContent) throws IOException {
		FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
		fos.write(fileContent.getBytes());
		fos.close();
	}
	
	public String read(String filename) throws IOException {
		FileInputStream fis = context.openFileInput(filename);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while((len = fis.read(buffer))!= -1) {
			bos.write(buffer, 0, len);
		}
		
		byte[] content = bos.toByteArray();
		fis.close();
		bos.close();
		
		return new String(content);
	}
}

//如果是保存应用自己的数据,如图片、视频等不要直接存放到sdcard的根目录下(即Environment.getExternalStorageDirectory得到的目录,
//或者在android2.2下的 /mnt/sdcard目录)
//应该通过此函数得到目录,这样卸载应用时相关目录会被删除(可以通过 type 指定应用下的音乐、视频、图片等子目录)
//如果type为空,返回的目录为/mnt/sdcard/Android/data/com.example.fileoperation/files
public abstract File Context.getExternalFilesDir(String type) 


//另一方面如果想要向“公用”的相册中写入或读取文件,可以用的方法为
public static File 即Environment.getExternalStoragePublicDirectory (String type)

SharedPreference (一般用于保存的软件参数)
public void save(String name, Integer age) {
	//使用方式
	SharedPreferences preferences = context.getSharedPreferences("itcast", Context.MODE_PRIVATE);
	Editor editor = preferences.edit();
	editor.putString("name", name);
	editor.putInt("age", age);
	editor.commit();
}
/**
 * 读
 * @return
 */
public Map<String, String> getPreferences(){
	Map<String, String> params = new HashMap<String, String>();
	SharedPreferences preferences = context.getSharedPreferences("itcast", Context.MODE_PRIVATE);
	params.put("name", preferences.getString("name", ""));
	params.put("age", String.valueOf(preferences.getInt("age", 0)));
	return params;
}


SQLite 简介:


用户第一次使用软件时,使用
SQLiteOpenHelper .getReadableDatabase() 或 .getWritableDatabase()
数据库默认保存在 <package-name>/databases/下
可以使用 SQLiteExpertSetup.exe 来管理 SQLite的数据库文件
//数据库帮助类
public class DBOpenHelper extends SQLiteOpenHelper {

	public DBOpenHelper(Context context) {
		//null 表示使用默认的
		//2 表示版本号,不能为 0
		super(context, "itcast.db", null, 2);//<包>/databases/
	}

	@Override
	public void onCreate(SQLiteDatabase db) {//是在数据库每一次被创建的时候调用的
		//可以在这里生成数据库表
		db.execSQL("CREATE TABLE person(personid integer primary key autoincrement, name varchar(20), phone VARCHAR(12) NULL)");
	}

	//当软件升级时,需要在数据库中额外添加数据结构,导致这个方法被调用
	//比如在构造方法中设置 version 为2 时就会调用此方法
	//如果第一次执行,肯定不会执行下面这个方法
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("ALTER TABLE person ADD amount integer");
	}

}

DBOpenHelper dbOpenHelper = new DBOpenHelper(getContext());
dbOpenHelper.getWritableDatabase();

关于SQLiteOpenHelper类的工作原理可以查看源代码,很容易理解;


注意上图中的翻页SQL语句


在调用 getReadableDatabase时会调用getWritableDatabase,但getWritableDatabase可能失败,
getWritableDatabase 方法可能失败(在数据库文件达到设定容量时)


//数据库操作示例
package cn.itcast.service;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import cn.itcast.domain.Person;

public class PersonService {
	private DBOpenHelper dbOpenHelper;

	public PersonService(Context context) {
		this.dbOpenHelper = new DBOpenHelper(context);
	}
	
	public void payment(){
		//注意 try-finally 的用法
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		db.beginTransaction();//开启事务
		try{
			db.execSQL("update person set amount=amount-10 where personid=1");
			db.execSQL("update person set amount=amount+10 where personid=2");
			db.setTransactionSuccessful();//设置事务的标志为True
		}finally{
			db.endTransaction();//结束事务,有两种情况:commit,rollback,
		//事务的提交或回滚是由事务的标志决定的,如果事务的标志为True,事务就会提交,否侧回滚,默认情况下事务的标志为False
		}
	}
	
	public void save(Person person){
		//如果在程序中只有一个地方使用数据库,可以不关闭数据库
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		db.execSQL("insert into person(name, phone, amount) values(?,?,?)",
				new Object[]{person.getName(), person.getPhone(), person.getAmount()});
	}
	
	public void delete(Integer id){
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		db.execSQL("delete from person where personid=?", new Object[]{id});
	}
	
	public void update(Person person){
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		db.execSQL("update person set name=?,phone=?,amount=? where personid=?",
				new Object[]{person.getName(), person.getPhone(),  person.getAmount(), person.getId()});
	}
	
	public Person find(Integer id){
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select * from person where personid=?", new String[]{id.toString()});
		if(cursor.moveToFirst()){//如果存在数据,才会返回true
			int personid = cursor.getInt(cursor.getColumnIndex("personid"));
			int amount = cursor.getInt(cursor.getColumnIndex("amount"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			String phone = cursor.getString(cursor.getColumnIndex("phone"));
			return new Person(personid, name, phone, amount);
		}
		cursor.close();
		return null;
	}
	/**
	 * 分页获取记录
	 * @param offset 跳过前面多少条记录
	 * @param maxResult 每页获取多少条记录
	 * @return
	 */
	public List<Person> getScrollData(int offset, int maxResult){
		List<Person> persons = new ArrayList<Person>();
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select * from person order by personid asc limit ?,?",
				new String[]{String.valueOf(offset), String.valueOf(maxResult)});
		while(cursor.moveToNext()){
			int personid = cursor.getInt(cursor.getColumnIndex("personid"));
			int amount = cursor.getInt(cursor.getColumnIndex("amount"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			String phone = cursor.getString(cursor.getColumnIndex("phone"));
			persons.add(new Person(personid, name, phone, amount));
		}
		cursor.close();
		return persons;
	}
	/**
	 * 分页获取记录
	 * @param offset 跳过前面多少条记录
	 * @param maxResult 每页获取多少条记录
	 * @return
	 */
	public Cursor getCursorScrollData(int offset, int maxResult){
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select personid as _id,name,phone,amount from person order by personid asc limit ?,?",
				new String[]{String.valueOf(offset), String.valueOf(maxResult)});
		return cursor;
	}
	
	/**
	 * 获取记录总数
	 * @return
	 */
	public long getCount(){
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("select count(*) from person", null);
		cursor.moveToFirst();
		long result = cursor.getLong(0);
		cursor.close();
		return result;
	}
}

除了execSQL 和 rawQuery 之外,还提供了 insert,delete,update,query (增删改查)操作,具体如下图:


package cn.itcast.service;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import cn.itcast.domain.Person;

public class OtherPersonService {
	private DBOpenHelper dbOpenHelper;

	public OtherPersonService(Context context) {
		this.dbOpenHelper = new DBOpenHelper(context);
	}
	/**
	 * 添加记录
	 * @param person
	 */
	public void save(Person person){
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("name", person.getName());
		values.put("phone", person.getPhone());
		values.put("amount", person.getAmount());
		db.insert("person", null, values); //这里的NULL字段有什么用
		/*
			如果 values为null或空集合,如果第二个参数为 name, 则相当于
			insert into person(name) values (NULL)
			具体还需要研究
		*/
	}
	/**
	 * 删除记录
	 * @param id 记录ID
	 */
	public void delete(Integer id){
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		db.delete("person", "personid=?", new String[]{id.toString()});
	}
	/**
	 * 更新记录
	 * @param person
	 */
	public void update(Person person){
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		ContentValues values = new ContentValues();
		values.put("name", person.getName());
		values.put("phone", person.getPhone());
		values.put("amount", person.getAmount());
		db.update("person", values, "personid=?", new String[]{person.getId().toString()});
	}
	/**
	 * 查询记录
	 * @param id 记录ID
	 * @return
	 */
	public Person find(Integer id){
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.query("person", null, "personid=?", new String[]{id.toString()}, null, null, null);
		
		if(cursor.moveToFirst()){
			int personid = cursor.getInt(cursor.getColumnIndex("personid"));
			int amount = cursor.getInt(cursor.getColumnIndex("amount"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			String phone = cursor.getString(cursor.getColumnIndex("phone"));
			return new Person(personid, name, phone, amount);
		}
		cursor.close();
		return null;
	}
	/**
	 * 分页获取记录
	 * @param offset 跳过前面多少条记录
	 * @param maxResult 每页获取多少条记录
	 * @return
	 */
	public List<Person> getScrollData(int offset, int maxResult){
		List<Person> persons = new ArrayList<Person>();
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		Cursor cursor = db.query("person", null, null, null, null, null, "personid asc", offset+ ","+ maxResult);
		
		while(cursor.moveToNext()){
			int personid = cursor.getInt(cursor.getColumnIndex("personid"));
			int amount = cursor.getInt(cursor.getColumnIndex("amount"));
			String name = cursor.getString(cursor.getColumnIndex("name"));
			String phone = cursor.getString(cursor.getColumnIndex("phone"));
			persons.add(new Person(personid, name, phone, amount));
		}
		cursor.close();
		return persons;
	}
	/**
	 * 获取记录总数
	 * @return
	 */
	public long getCount(){
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		//注意 count(*) 在这里怎么写
		Cursor cursor = db.query("person", new String[]{"count(*)"}, null, null, null, null, null);
		cursor.moveToFirst();
		long result = cursor.getLong(0);
		cursor.close();
		return result;
	}
}

SimpleAdapter 仔细想想好直接呀,直接使用就行了(具体可以听下视频 czbo liming lecture19)代码如下;

private void show() {
	List<Person> persons = personService.getScrollData(0, 20);
	List<HashMap<String, Object>> data = new ArrayList<HashMap<String,Object>>();
	for(Person person : persons){
		HashMap<String, Object> item = new HashMap<String, Object>();
		item.put("name", person.getName());
		item.put("phone", person.getPhone());
		item.put("amount", person.getAmount());
		item.put("id", person.getId());
		data.add(item);
	}
	//data是List<Map<String,?>>类型,而new String[]{,}指定key, int[]{,}指定小控件id
	SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item,
			new String[]{"name", "phone", "amount"}, new int[]{R.id.name, R.id.phone, R.id.amount});
	
	listView.setAdapter(adapter);
	
}

//小心 _id 异常
private void show2() {
	Cursor cursor = personService.getCursorScrollData(0, 20);
	SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor,
			new String[]{"name", "phone", "amount"}, new int[]{R.id.name, R.id.phone, R.id.amount});
	listView.setAdapter(adapter);
}

如果表里没有 _id,可以命名一个别名,如下

Cursor cursor = db.rawQuery("select personid as _id,name,phone,amount from person order by personid asc limit ?,?",
				new String[]{String.valueOf(offset), String.valueOf(maxResult)});

如果是SimpleAdapter 或 CursorAdapter 点击ListView单项时得到的是什么类型呢? 可以看源代码
SimpleAdapter: Map<String, ?>
CursorAdapter: Cursor (已经移到相关位置, cursor.moveToPostion(position))


15.Content Provider
简介如下图:


content provider 使用 uri 指定操作的数据(就像访问网站上的某个网页一样),详细描述如下:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值