一.菜单Menu
1.OptionsMenu 选项菜单 也叫系统菜单,右上角的三点
(1)高版本的菜单
Step1: 在menu文件夹中的XMl文件中写菜单布局
<item
android:id="@+id/action_color"
android:orderInCategory="100"控制再Menu中显示的顺序,数值越 小,越靠前
android:showAsAction="never"控制该菜单项何时显示再ActionBar中
属性:never 永远不现实再ActionBar中
always 一直显示再Action Bar中
ifRoom如果有空间,则显示再ActionBar中
android:title=“菜单项的文本”/>
//<item>元素中可嵌套<menu>元素形成二级菜单
Step2:在Activity中调用onCreateOptionsMenu方法
public boolean onCreateOptionsMenu(Menu menu){
//加载菜单布局
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
Step3:重写点击菜单回调的方法
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
.......
}
}
(2)低版本创建菜单,纯java代码
在Activity中重写onCreateOptionsMenu方法
public boolean onCreateOptionsMenu(Menu menu){
menu.add(menu.NONE,1,menu.NONE,"低版本的菜单一");
SubMenu subMenu = menu.addSubMenu(menu.NONE,2,menu.NONE,"sub 2");
subMenu.add(menu.NONE,21,1,"sub 2_1");
subMenu.add(menu.NONE,22,0,"sub 2_2");
return true;
}
2.ContextMenu 上下文菜单
可以为任意View指定上下文菜单,长按View显示上下文菜单,
通常用于ListView和GridView中
(1)在menu文件夹下的XML文件中写布局
(2)为View注册上下文菜单
registerForContextMenu(textView);
(3)重写Activity中的onCreateContextMenu()方法
/**
*创建上下文菜单,长按View时调用该方法,每长按一次就会被调用一次
*ContextMenu menu 需要显示的菜单
*View view 被长按的view,且经过注册
*ContextMenuInfo menuInfo所选择界面的额外信息(ListView,GridView,Spinner)
* 携带的AdapterView中的position信息
*/
public void onCreateContextMenu(ContextMenu menu,View view,ContextMenuinfo menuInfo){
//加载菜单布局
getMenuInflater().inflate(R.menu.xxx,menu);
position = ((AdapterContextMenuInfo)menuInfo).position;
}
(4)重写onContextItemSelected方法,点击上下文菜单项被回调的方法
public boolean onContextItemSelected(MenuItem item){
switch(item.getItemId){
........
}
}
3.弹出式菜单 PopupMenu API 11 以上,可以为任意一个View创建弹出式菜单
(1)创建弹出式菜单
/**
*this 上下文
*v 当前弹出式菜单参考显示位置的UI控件
*/
PopupMenu popupMenu = new PopupMenu(this,v);
(2)加载菜单内容
getMenuInflater().inflate(R.menu.xxx,popupMenu.getMenu());
(3)为弹出式菜单添加点击事件
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener(){
public boolean onMenuItemClick(Menuitem item){
switch(item.getItemId){
...........
}
}
});
(4)显示弹出式菜单
popuMenu.show();
二、对话框
常用对话框
普通对话框 AlertDialog
进度条对话框 ProgressDialog
日期选择对话框 DatePickerDialog
时间选择对话框 TimePickerDialog
自定义对话框 setView()
列表对话框(在AlertDialog的基础上设置某些属性而得)
普通列表对话框
builder.setItems(数组,new Dialoginterface.OnClickListener{})
单选列表对话框
builder.setSingleChoiceItems(数组,new Dialoginterface.OnclickListener{})
多选列表对话框
builder.setMultiChoiceItems(数组,new OnMultiChoiceClickListener{})
适配器列表对话框
builder.setAdapter(数组,new Dailoginterface.OnclickListener{})
对话框的通用属性
setIcon(R.drawable.ic_launcher) 设置对话框的标题头像
setTitle("") 设置标题
setMessage("") 设置内容文字
setCancelable(ture/false) 设置点击空表出对话框是否消失
三、Android的存储
一.共享参数存储 (SharedPreferences)
(1)SharedPreferences的介绍
SharedPreferences是Android系统提供的一个通用的数据持久化框架,用于存储和读取key-value类型的原始基本数据类型对,目前支持String、int、long、float、boolean等基本类型的存储,对于自定义的对象数据类型,无法使用SharedPreferences来存储。
SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名,上次最后设置的配置信息(如:是否打开音效、是否使用振动,小游戏的玩家积分等)。
当再次启动程序后依然保持原有设置。SharedPreferences用键值对方式存储,方便写入和读取。
SharedPreferences是Context上下文中的一个接口,Context提供了一个getSharedPreferences(name,mode)方法用于拿到SharedPreferences对象
SharedPreferences里又有一个Editor接口,SharedPreferences对象中提供了一个edit()方法用于拿到Editor对象
(2)SharedPreferences的特点
存放轻量级数据
本质存储形式是xml格式
通常用于存储简单的数据信息,如记住账号,配置信息等
应用程序卸载后,文件也会被删除
(3)SharedPreferences存储的数据类型
可以存放boolean,int,string,long,float,
但不能存放对象.
(4)getSharedpreferences(name,mode)方法的介绍
该方法返回SharedPreferences对象,
该方法有两个参数:
第一个:String name 文件名
第二个:int mode 一些权限 Context中提供了一些常量
Context.MODE_PRIVATE : 只有本应用可以访问
Context.MODE_WORLD_READABLE :其他应用可读
Context.MODE_WORLD_WRITEABLE : 其他应用可写
这些权限可以用+号来连接
(5)SharedPreferences常用方法
sharedPreferences.edit();获取Editor对象
sharedPreferences.getXXX(key,默认值);
如:sharedPreferences.getString(key,默认值);
sharedPreferences.getStringSet(key,默认set); 返回set
sharedpreferences.getAll() 返回Map<String,?>
sharedPreferences.contains(key) 判断是否存在某键
editor.putXXX(key,默认值)
editor.putStringSet(key,默认Set)
editor.remove(key); 移除某键值对
editor.clear(); 清楚所有数据.
editor.commit(); 提交,如果不提交则写不到文件中去
(6)SharedPreferences使用步骤
①通过context对象得到sharedpreferences对象
Sharedpreferences sharedpreferences = context.getSharedPreferences("name",Context.MODE_PRIVATE);
②拿个Editor对象,并put数据
Editor editor = sharedpreferences.editor();
editor.putString(key,默认值);
........
editor.commit();数据成功存入
③通过sharedpreferences对象拿值
sharedpreferences.getString(key,默认值);
........
二.File存储
(1)内部存储 Internal Storage
<1>特点: 文件只能被本应用访问,其他应用不能访问
当应用程勋卸载后,程序在内部存储的文件也会被删除
<2>路径:
data/data/应用程序包名/files/***.**
<3>核心方法:
context提供了openInputStream(name); 根据指定文件名打开输入流
openOutputStream(name,mode); 根据文件名打开输入流,无则创建.
mode同SharedPreferences一样
String[] fileList() 获取所有文件名称
File getFileDir() 获取文件的绝对路径
boolean deleteFile(name)删除某个文件
(2)外部存储 external storage(扩展卡 SD卡)
<1>特点:SD卡公共目录 SD卡的私有目录
公共目录下的文件可以被应用程序共享,私有目录中的文件只能当前应用程序使用.当程序卸载后,公共目录中的文件不被清理,私有目录中的文件会被清理
<2>权限:
<!--写SD卡的权限-->
<user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--读SD卡的权限-->
<users-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<3>SD卡的根目录
File file = Environment.getExternalStorageDirectory();
打印结果为:/mnt/sdcard
<4>SD卡公共目录
Environment.getExternalStoragePublicDirectory(String type)
参数type:
DIRECTORY_ALARMS //警报的铃声
DIRECTORY_DCIM //相机拍摄的图片和视频保存的位置
DIRECTORY_DOWNLOADS //下载文件保存的位置
DIRECTORY_MOVIES //电影保存的位置, 比如 通过google play下载 的电影
DIRECTORY_MUSIC //音乐保存的位置
DIRECTORY_NOTIFICATIONS //通知音保存的位置
DIRECTORY_PICTURES //下载的图片保存的位置
DIRECTORY_PODCASTS //用于保存podcast(博客)的音频文件
DIRECTORY_RINGTONES //保存铃声的位置
打印结果为:/mnt/sdcard/alarms
<5>SD卡的私有目录
context.context.getExternalFilesDir(null) SD卡的私有目录的根目录
打印结果为:/mnt/sdcard/Android/data/包名/files
context.getExternalFilesDir(String type) SD卡的私有目录中的指定目录
context.getExternalCacheDir() SD卡的私有目录的缓存目录
打印结果为:/mnt/sdcard/Android/data/包名/cache
<6>获取SD卡的状态
Environment.getExternalStorageState()
<7>读写SD卡的步骤
①判断SD卡的状态
Environment.getExternalStorageState()
②获取sdcard的路径
Environment.getExternalStorageDirectory()
③添加读写SD卡的权限
④执行IO操作
<8>利用StatFs获取磁盘空间信息
StatFs 一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况
StatFs的常用方法: 以block为单位.
getAvailableBlocks() 返回int,可用数据块个数
getFreeBlocks() 返回int,可用数据块个数,与上一个方法一样
getBlockCount() 返回int,总数据块数
getBlockSize() 返回int,大小,以字节为单位,每个数据块的大小
restate(String path) 执行一个由该对引用的文件系统
SDK>=18时
statFs.getFreeBytes() 直接返回磁盘的剩余空间
SDK<18时
statFs.getFreeBlocks()*statFs.getBlockSize() 计算剩余空间
三.SQLite数据库存储
(1)特点
轻量级 绿色 零配置 跨平台 嵌入式
在程序的内部,可以在任何位置通过数据库的名称访问数据库,不可跨应用访问
路径:data/data/应用程序包名/database/**.db
(2)SQLite知识,同java笔记
(3)Android操作SQlite数据库的核心类
<1>SQLiteDatabase的使用
SQLiteDatabase用于管理和操作数据库
context对象中提供了一个返回SQLiteDatabase对象的方法
context.openOrCreateDatabase(name,mode,CursorFactory);
参数:
name : 数据库名称
mode : 模式: SQliteDatabase.OPEN_READWRITER 读写模式
SQLiteDatabase.OPEN_READONLY 只读模式
SQLiteDatabase.CREATE_IF_NECESSARY 如果数据 库不存在,则创建
CursorFactory: 通常为空
SQLiteDatabase中执行SQL语句的方法: (常用)
void execSQL(String sql) 执行SQL语句
void execSQl(String sql,Object[] bindArgs) 执行SQL语句(可以有占位符)
Cursor rawQuery(String sql,String[] selectionArgs) 执行查询语句(可以有占位符)
SQLiteDatabase封装好的操作数据库的方法 (不常用)
insert() 插入数据到指定的表中
update() 更改表中指定的数据
delete() 删除表中指定的数据
query() 查询表中指定的内容
<2>SQLiteOperHelper 维护了一个数据库及维护了一个SQLiteDatabase对象
用于数据的创建.更新.和打开数据库连接
用法:
①定义一个类,继承SQLiteOpenHelper
并重写父类的两个方法,这两个方式是系统调用的不用手动调用
onCreate(SQLiterDatabase db) 第一次创建数据库时调用, 只会被调用一次
onUpgrade(SQLiterDatabase db,int oldVersion, int newVersion) 数据库的版本号发生变化后,执行此方法(可能会被执行多次)
②必须提供一个构造方法
public MySQLiteOpenHelper(Context context) {
super(context, name, CursorFactory, version);
}
参数:
context: 上下文对象
name: 数据库名字
CursorFactory:通常为null,就是用系统的CursorFactory
version: 版本号
SqLiteOpenHelper对象中的方法
mySQLiteOpenHelper.getReadableDatabase();只读方式打开数据库连接
mySQLiteOpenHelper.getWritableDatabase();以读写方式打开数据库连接
<3>Cursor
作用类似于JDBC中resultSet, 把查询的结果封装到Cursor对象中.
cursor就像是一个结果级上的游标, 可以向上或向下移动
默认游标位置在数据的上方
cursor对象的常用方法:
coursor.getCount() 得到游标中的数据数量
coursor.moveToNext() 游标移动到下一条数据, 并且判断下一条数据是否存在
coursor.moveToPrevious() 游标移动到上一条数据, 并且判断上一条数据是否存在
coursor.moveToFirst() 游标移动到第一条数据, 并且判断第一条数据是否存在
coursor.moveToLast() 游标移动到最后一条数据, 并且判断最后一条数据是否存在
coursor.moveToPosition(int position) 游标移动到某一条数据, 并且判断某一条数据是否存在
coursor.move(int offset) 游标向上或者向下移动指定的行数, 正数代表向上,负数代表向下, 并且判断数据是否存在
cursor.getColumnIndex(columnName) 根据列名拿个下标2016/7/6
cursor.getColumnName(columnIndex) 根据下标拿个列名
cursor.getColumnNames() 得到所有列名组成的数组
cursor.getPosition() 得到行标
四.Content Provider 内容提供者(Android四大组件之一)
(1)Content Provider的介绍,作用以及特点
为了达到不同应用程序之间的数据共享,Android提供了ContentProvider.
例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过 ContentProvider来满足我们的需求了
<1>ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
<2>使用ContentProvider可以在不同的应用程序之间共享数据。
<3>Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。
总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。
(2)ContentProvider类的介绍
ContentProvider是一个抽象类,要想创建ContentProvider必须自定义一个类继承ContentProvider并实现其中的抽象方法:
public boolean onCreate():该方法在ContentProvider创建后就会被调用, Android开机后,ContentProvider在其它应用第一 次访问它时才会被创建。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于供外部应用从 ContentProvider中获取数据。
public Uri insert(Uri uri, ContentValues values):该方法用于供外部应用往 ContentProvider添加数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于供外部应用更新 ContentProvider中的数据。
public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于供 外部应用从ContentProvider删除数据。
public String getType(Uri uri):该方法用于返回当前Url所代表数据的MIME类型。
如果操作的数据属于集合类型,那么MIME类型字 符串应该以vnd.android.cursor.dir/开头,
如果要操作的数据属于非集合类型数据,那么 MIME类型字符串应该以vnd.android.cursor.item/开头,
创建自己的ContentProvider步骤:
①封装CONTENT_URI(必须是唯一的字符串,常用Contentprovider完全限定名)
和数据库表的列名,必须为其定义一个叫_id的列,它用来表示每条记录的唯一性。
public class MyUsers {
public static final String AUTHORITY = “com.wissen.MyContentProvider”;
// BaseColumn类中已经包含了 _id字段和_COUNT字段
public static final class User implements BaseColumns {
public static final Uri CONTENT_URI = Uri.parse(”content://com.wissen.MyContentProvider”);
// 表数据列
public static final String USER_NAME = “USER_NAME”;
}
}
②定义自己的MyContentProvider类继承ContentProvider,实现其中的抽象方法
③实现SQLiteOpenHelper对数据库的操作,一共②使用.
④在AndroidManifest.xml中配置ContentProvider
<provider android:name="MyContentProvider"
android:authorities="包名.类名“/>
(3)ContentReslover类的介绍
<1>ContentReslover的作用和特点
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,ContentReslover是一个抽象类,不能new出其实例,Context提供了getContentResLover()方法
<2>ContentReslover的常用方法
ContentResolver 类提供了与ContentProvider类相同签名的四个方法:
public Uri insert(Uri uri, ContentValues values):该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于从ContentProvider中获取数据。
参数:uri 同上解释
projection 要返回的列名组成的数组
selecttion 条件字符串,包含占位符
selectionArgs 上面占位符要显示的内容组成的数组
sortOrder 排列顺序
这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,其实和contentprovider里面的方法是一样的.他们所对应的数据,最终是会被传到我们在之前程序里面定义的那个contentprovider类的方法,假设给定的是:Uri.parse("content://com.bing.providers.personprovider/person/10"),那么将会对主机名为com.bing.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。
<3>ContentReslover的使用步骤
①获取ContentReslover对象
ContentResolver resolver = getContentResolver();
②指定URI
Uri uri = Uri.parse("content://com.bing.provider.personprovider/person");
③调用contentReslover的方法指定操作
//添加一条记录
ContentValues values = new ContentValues();
values.put("name", "bingxin");
values.put("age", 25);
resolver.insert(uri, values);
//获取person表中所有记录
Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
while(cursor.moveToNext()){
Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));
}
//把id为1的记录的name字段值更改新为zhangsan
ContentValues updateValues = new ContentValues();
updateValues.put("name", "zhangsan");
Uri updateIdUri = ContentUris.withAppendedId(uri, 2);
resolver.update(updateIdUri, updateValues, null, null);
//删除id为2的记录
Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);
resolver.delete(deleteIdUri, null, null);
<4>系统提供的ContentProvider已经封装好的URI
(4)URI的介绍
URI叫做统一资源标识符,代表要操作的数据,这样你就可以找到对应的 ContentProvider以及想要的数据.(URI也可以说是一种类似SQL的查询语句)
URI的格式:
content://com.example.transportationprovider/trains/122
该URI可以根据反斜杠来划分为四部分
content:// : 协议部分类似于http://,不可改变
com.example.transportationprovider : 该部分是URI的授权部分,是唯一标识,用来定位ContentProvider.一般定义为Contentprovider的完全限定名,注册时需要用到
trains/122 : 内部路径部分, trains指向一个集合,一般用表名来表示,"122"为_id.单条数据的标识,如果没有"122"则返回一个数据集,有"122"则返回一条数据
(5)UriMatcher类的介绍
因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
首先第一步把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.bing.procvide.personprovider/person路径,返回匹配码为1
sMatcher.addURI("com.bing.procvide.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://com.bing.provider.personprovider/person/230路径,返回匹配码为2
sMatcher.addURI("com.bing.provider.personprovider", "person/#", 2);//#号为通配符
switch(sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
(6)ContentUris类的介绍
ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分:
parseId(uri)方法用于从路径中获取ID部分:
(7)监听ContentProvider中数据的变化
如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,
则需要有两个步骤
①ContentProvider需要在数据发生变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者
例:
public class PersonContentProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
db.insert("person", "personid", values);
getContext().getContentResolver().notifyChange(uri, null);
}
}
②ContentProvider的访问者必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:
contentProvider对象调用registerContentObserver(uri, notifyForDescendents, observer);注册监听
参数说明: URI 要监听数据的URI
notifyForDescendents true/false
observer ContentObserver实例,其中实现了onChange方法
例:
getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),
true, new PersonObserver(new Handler()));
public class PersonObserver extends ContentObserver{
public PersonObserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange) {
//此处可以进行相应的业务处理
}
}
(8)操作Android系统短息信息
(9)操作Android系统通话记录
(10)操作Android系统联系信息
(11)操作Android图片信息
(12)操作Android音频信息
(13)操作Android视频信息