下面一一介绍Preferences的使用 Preferences:一个轻量级机制,存储和获得原始数据类型的关键词。这是典型的用来存储数据的首选项。 你能享受存储应用程序优先级,就像一个默认的招呼或者是无论何时开始运行应用程序时的文本字体。调用Context.getSharePreferences()读和写数据值。为你所设置的首先项分配一个名称,如果你想将它们分享给同一个包中的其他组件的话,或者是使用Activity.getPreferences()去使它们作为私有使用,这时此函数不需要任何参数。 下面是一个例子: public class Calc extends Activity { public static final String PREFS_NAME = "MyPrefsFile"; ...
@Override protected void onCreate(Bundle state){ super.onCreate(state); ... // Restore preferences SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); /* public abstract SharedPreferences getSharedPreferences(String name, int mode) Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values. Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they will see each other's edits as soon as they are made. Parameters name Desired preferences file. If a preferences file by this name does not exist, it will be created when you retrieve an editor (SharedPreferences.edit()) and then commit changes (Editor.commit()). mode Operating mode. Use 0 or MODE_PRIVATE for the default operation, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE to control permissions. Returns
* Returns the single SharedPreferences instance that can be used to retrieve and modify the preference values.
*/ boolean silent = settings.getBoolean("silentMode", false); setSilent(silent); } @Override protected void onStop(){ super.onStop(); // Save user preferences. We need an Editor object to // make changes. All objects are from android.context.Context SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean("silentMode", mSilentMode);
// Don't forget to commit your edits!!! editor.commit(); } }
使用文件Files Android为本地应用程序提供了读和写流,调用函数Context.openFileOutput()和Context.openFileInput() 去读和写文件,这需要参数:本地名称和路径。你仅仅能获得当前文件,而不能获得另外一个应用程序的文件。 如果你在编译期间有静态文件存在于你所运行的应用程序包中,你可以保存你的文件到你的当前工程中的res/raw/ 中,之后使用Resources.openRawResource(R.raw.mydatafile)来实现。 来看看函数Context.openFileOutput()和函数Context.openFileInput(): Context.openFileOutput() 打开一个用来执行写操作的的私有文件,这个私有文件是与当前上下文应用程序包相互关联的。如果文件不存在,那么 就会创建一个。 参数解释: name 打开文件的名称,但是不能包含路径分隔符The name of the file to open; can not contain path separators. mode 操作模式,使用值0或是MODE_PRIVATE作为默认应用操作。MODE_APPEND即向一个存在的文件追加内容, MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE用来控制权限。Operating mode. Use 0 or MODE_PRIVATE for the default operation, MODE_APPEND to append to an existing file, MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE to control permissions. 返回值: *产生输出流的 FileOutputStream。
Context.openFileInput() 函数原型: public abstract FileInputStream openFileInput(String name) 打开一个用来进行读操作的私有文件,这个文件与当前上下文的应用程序包相关连。 Open a private file associated with this Context's application package for reading. 参数: name 打开文件的名称,但是不能包含路径分隔符 Returns * 产生输入流的FileInputStream。
前面所说的知识都不能在应用程序之间进行共享,现在来说说如何在不同的应用之间进行数据的共享。 Content Providers实现上面所说的共享问题,在Android中,这是唯一一个用来进行数据共享的方法。 下面来具体介绍如何使用Context Provider 使用Content Provider (一)数据查询 1、每一个contact provider都是通过提供一个公有的URI,这个URI被一个客户用来在对应content provider 中查询 /增加/更新/删除数据。这个URI有两种格式:一个是返回所有的contact,另外一个返回具体的结果。例如: content://contacts/people/ content://contacts/people/23 我们现在来看看下面的一段代码: // Get the base URI for contact with _ID=23. // This is same as Uri.parse("content://contacts/people/23"); Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23); // Query for this record. Cursor cur = managedQuery(myPerson, null, null, null); 这段代码返回一个查询结果的光标, 你应该使用Activity.managedQuery()方法去获得一个管理光标。一个处理光标操作所有的具体操作,就像你在运 行一段程序的过程中,暂停了,那么就需要Cursor来保存现场,当再次回来时,就可以继续运行了。还有一个更加方 便的方法就是startManagingCursor(),这使用起来更加地方便。 函数原型: public final Cursor managedQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) Wrapper around query(android.net.Uri, String[], String, String[], String) that gives the resulting Cursor to call startManagingCursor(Cursor) so that the activity will manage its lifecycle for you. 参数: uri The URI of the content provider to query. projection List of columns to return. selection SQL WHERE clause. selectionArgs The arguments to selection, if any ?s are pesent sortOrder SQL ORDER BY clause. Returns
* The Cursor that was returned by query().
(二)更改数据 如果要成批地更新记录,调用函数ContentResolver.update(),参数为要改变的columns和values. public final int update(Uri uri, ContentValues values, String where, String[] selectionArgs) Update row(s) in a content URI. If the content provider supports transactions the update will be atomic. Parameters uri The URI to modify. values The new field values. The key is the column name for the field. A null value will remove an existing field value. where A filter to apply to rows before deleting, formatted as an SQL WHERE clause (excluding the WHERE itself). Returns
(四)删除记录 调用ContentResolver.delete(),参数为指定的URI删除一个单一的记录。 Creating a Content Provider 下面是关于如何创建自己的content provider的方法步骤: Here is how to create your own content provider to act as a public source for reading and writing a new data type:
1. Extend ContentProvider. 2. Define a public static final Uri named CONTENT_URI. This is the string that represents the full "content://" URI that your content provider handles. You must define a unique string for this value; the best solution is to use the fully-qualified class name of your content provider (lowercase). So, for example: public static final Uri CONTENT_URI = Uri.parse( "content://com.google.codelab.rssprovider"); 3. Create your system for storing data. Most content providers store their data using Android's file storage methods or SQLite databases, but you can store your data any way you want, so long as you follow the calling and return value conventions. 4. Define the column names that you will return to your clients. If you are using an underlying database, these column names are typically identical to the SQL database column names they represent. In any case, you should include an integer column named _id to define a specific record number. If using the SQLite database, this should be type INTEGER PRIMARY KEY AUTOINCREMENT. The AUTOINCREMENT descriptor is optional, but by default, SQLite autoincrements an ID counter field to the next number above the largest existing number in the table. If you delete the last row, the next row added will have the same ID as the deleted row. To avoid this by having SQLite increment to the next largest value whether deleted or not, then assign your ID column the following type: INTEGER PRIMARY KEY AUTOINCREMENT. (Note You should have a unique _id field whether or not you have another field (such as a URL) that is also unique among all records.) Android provides the SQLiteOpenHelper class to help you create and manage versions of your database. 5. If you are exposing byte data, such as a bitmap file, the field that stores this data should actually be a string field with a content:// URI for that specific file. This is the field that clients will call to retrieve this data. The content provider for that content type (it can be the same content provider or another content provider — for example, if you're storing a photo you would use the media content provider) should implement a field named _data for that record. The _data field lists the exact file path on the device for that file. This field is not intended to be read by the client, but by the ContentResolver. The client will call ContentResolver.openOutputStream() on the user-facing field holding the URI for the item (for example, the column named photo might have a value content://media/images/4453). The ContentResolver will request the _data field for that record, and because it has higher permissions than a client, it should be able to access that file directly and return a read wrapper for that file to the client. 6. Declare public static Strings that clients can use to specify which columns to return, or to specify field values from the cursor. Carefully document the data type of each field. Remember that file fields, such as audio or bitmap fields, are typically returned as string path values 7. Return a Cursor object over a recordset in reply to a query. This means implementing the query(), update(), insert(), and delete() methods. As a courtesy, you might want to call ContentResolver.notifyChange() to notify listeners about updated information. 8. Add a tag to AndroidManifest.xml, and use its authorities attribute to define the authority part of the content type it should handle. For example, if your content type is content://com.example.autos/auto to request a list of all autos, then authorities would be com.example.autos. Set the multiprocess attribute to true if data does not need to be synchronized between multiple running versions of the content provider. 9. If you are handling a new data type, you must define a new MIME type to return for your implementation of android.ContentProvider.getType(url). This type corresponds to the content:// URI submitted to getType(), which will be one of the content types handled by the provider. The MIME type for each content type has two forms: one for a specific record, and one for multiple records. Use the Uri methods to help determine what is being requested. Here is the general format for each: * vnd.android.cursor.item/vnd.yourcompanyname.contenttype for a single row. For example, a request for train record 122 using
might return the MIME type vnd.android.cursor.item/vnd.example.rail * vnd.android.cursor.dir/vnd.yourcompanyname.contenttype for multiple rows. For example, a request for all train records using
might return the MIME type vnd.android.cursor.dir/vnd.example.rail
For an example of a private content provider implementation, see the NodePadProvider class in the notepad sample application that ships with the SDK.
Here is a recap of the important parts of a content URI:
Elements of a content URI
1. Standard required prefix. Never modified. 2. Authority part. For third-party applications, this should be a fully-qualified class to ensure uniqueness. This corresponds to the value in the element's authorities attribute: 3. The path that the content provider uses to determine what kind of data is being requested. This can be zero or more segments: if the content provider exposes only one type of data (only trains, for example), this can be absent. If it provides several types, including subtypes, this can be several elements long: e.g., "land/bus, land/train, sea/ship, and sea/submarine" to give four possibilities. 4. A specific record being requested, if any. This is the _id value of a specific record being requested. If all records of a specific type are being requested, omit this and the trailing slash: content://com.example.transportationprovider/trains