一.菜单Menu
1.OptionsMenu 选项菜单 也叫系统菜单,右上角的三点
(1)高版本的菜单
Step1: 在menu文件夹中的XMl文件中写菜单布局
android:id="@+id/action_color" android:orderInCategory="100"控制再Menu中显示的顺序,数值越 小,越靠前 android:showAsAction="never"控制该菜单项何时显示再ActionBar中 属性:never 永远不现实再ActionBar中 always 一直显示再Action Bar中 ifRoom如果有空间,则显示再ActionBar中 android:title=“菜单项的文本”/> // 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) 设置点击空表出对话框是否消失 一.共享参数存储 (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 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>权限: <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 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视频信息二、对话框
三、Android的存储