Plist文件
应用程序特定的plist文件可以被保存到app bundle的Resources文件夹。当应用程序运行起来的时候,就会去检查是不是有一个plist文件在用户的Documents文件夹下。假如没有的话,就会从app bundle目录下拷贝过来。
// Look in Documents for an existing plist file
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
myPlistPath = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithFormat: @"%@.plist", plistName] ];
[myPlistPath retain];
// If it's not there, copy it from the bundle
NSFileManager *fileManger = [NSFileManager defaultManager];
if ( ![fileManger fileExistsAtPath:myPlistPath] ) {
NSString *pathToSettingsInBundle = [[NSBundle mainBundle]
pathForResource:plistName ofType:@"plist"];
}
现在我们就可以从Documents文件夹去读plist文件了。
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *path = [documentsDirectoryPath
stringByAppendingPathComponent:@"myApp.plist"];
NSMutableDictionary *plist = [NSDictionary dictionaryWithContentsOfFile: path];
Now read and set key/values
myKey = (int)[[plist valueForKey:@"myKey"] intValue];
myKey2 = (bool)[[plist valueForKey:@"myKey2"] boolValue];
[plist setValue:myKey forKey:@"myKey"];
[plist writeToFile:path atomically:YES];
ContentProvider 的使用(1)
1)新建Android 项目,成功后,先编写我自己的Employee 类:
/*
* Copyright (C) Mesada Technologies Co., Ltd. 2005-2011.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Mesada Technologies Co., Ltd. ("Confidential Information").
* You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement
* you entered into with Mesada.
*/
package com.mesada.demo;
import android.net.Uri;
/**
* 实体类,封装了相关的一些常量信息.
*
* @author Xiaolong Long
* @date 2011-3-10
* @version 1.0
*/
public class Employee {
public static final String MIME_DIR_PREFIX = "vnd.android.cursor.dir";
public static final String MIME_ITEM_PREFIX = "vnd.android.cursor.item";
public static final String MIME_ITEM = "vnd.mesada.employee";
//MIME:表示单一数据
public static final String MIME_TYPE_SINGLE = MIME_ITEM_PREFIX + "/"
+ MIME_ITEM;
//MIME:表示多条数据
public static final String MIME_TYPE_MULTIPLE = MIME_DIR_PREFIX + "/"
+ MIME_ITEM;
public static final String AUTHORITY = "com.mesada.demo.provider.employeeprovider";
public static final String PATH_SINGLE = "employee/#";
public static final String PATH_MULTIPLE = "employee";
public static final String STR = "content://" + AUTHORITY + "/"
+ PATH_MULTIPLE;
public static final Uri CONTENT_URI = Uri.parse(STR);
public static final String ID = "_id";
public static final String NAME = "name";
public static final String AGE = "age";
}
2)新建类,继承自ContentProvider,并重写其接口函数,代码如下:
/*
* Copyright (C) Mesada Technologies Co., Ltd. 2005-2011.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Mesada Technologies Co., Ltd. ("Confidential Information").
* You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement
* you entered into with Mesada.
*/
package com.mesada.demo.provider;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import com.mesada.demo.Employee;
/**
* A Content Provider about Employee,Content providers are one of the primary
* building blocks of Android applications, providing content to applications.
* They encapsulate data and provide it to applications through the single
* ContentResolver interface. A content provider is only required if you need to
* share data between multiple applications. For example, the contacts data is
* used by multiple applications and must be stored in a content provider. If
* you don't need to share data amongst multiple applications you can use a
* database directly via SQLiteDatabase.
*
*
* When a request is made via a ContentResolver the system inspects the
* authority of the given URI and passes the request to the content provider
* registered with the authority. The content provider can interpret the rest of
* the URI however it wants. The UriMatcher class is helpful for parsing URIs.
*
*
* @author Xiaolong Long
* @date 2011-3-14
* @version 1.0
*/
public class EmployeeProvider extends ContentProvider {
private static final String DB_NAME = "mesada.db";
private static final String DB_TABLE = "employee";
private static final int DB_VERSION = 1;
private Context mContext;
private SQLiteDatabase mDb;
private DBOpenHelper mDBOpenHelper;
private static final int MULTIPLE_EMPLOYEE = 1;
private static final int SINGLE_EMPLOYEE = 2;
private static final UriMatcher mUriMatcher;
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(Employee.AUTHORITY, Employee.PATH_MULTIPLE,
MULTIPLE_EMPLOYEE);
mUriMatcher.addURI(Employee.AUTHORITY, Employee.PATH_SINGLE,
SINGLE_EMPLOYEE);
}
@Override
public String getType(Uri uri) {
// 根据给定的URI,返回相应的 MIME 类型
int code = mUriMatcher.match(uri);
switch (code) {
// 返回表示多个选项的MIME类型
case MULTIPLE_EMPLOYEE:
return Employee.MIME_TYPE_MULTIPLE;
// 返回表示单条记录的MIME类型
case SINGLE_EMPLOYEE:
return Employee.MIME_TYPE_SINGLE;
default:
throw new IllegalArgumentException("Unknown Uri:" + uri);
}
}
@Override
public boolean onCreate() {
mContext = getContext();
mDBOpenHelper = new DBOpenHelper(mContext, DB_NAME, null, DB_VERSION);
try {
mDb = mDBOpenHelper.getWritableDatabase();
} catch (Exception e) {
mDb = mDBOpenHelper.getReadableDatabase();
}
if (mDb != null) {
return true; // 数据提供者被成功载入
} else {
return false; // 数据提供者载入失败
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
int code = mUriMatcher.match(uri);
switch (code) {
case MULTIPLE_EMPLOYEE:
count = mDb.delete(DB_TABLE, selection, selectionArgs);
break;
case SINGLE_EMPLOYEE:
String str = uri.getPathSegments().get(1);
count = mDb
.delete(DB_TABLE, Employee.ID + "=" + str, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown Uri:" + uri);
}
// 执行相应操作后,需要通知observer(观察者),databases产生变化
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
long id = mDb.insert(DB_TABLE, null, values);
if (id > 0) {
Uri newUri = ContentUris.withAppendedId(Employee.CONTENT_URI, id);
// 执行相应操作后,需要通知observer(观察者),databases产生变化
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(DB_TABLE);
int code = mUriMatcher.match(uri);
switch (code) {
case SINGLE_EMPLOYEE:
qb.appendWhere(Employee.ID + "=" + uri.getPathSegments().get(1));
break;
default:
break;
}
Cursor cursor = qb.query(mDb, projection, selection, selectionArgs,
null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count;
int code = mUriMatcher.match(uri);
switch (code) {
case MULTIPLE_EMPLOYEE:
count = mDb.update(DB_TABLE, values, selection, selectionArgs);
break;
case SINGLE_EMPLOYEE:
String segment = uri.getPathSegments().get(1);
count = mDb.update(DB_TABLE, values, Employee.ID + "=" + segment,
selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknow URI:" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
public class DBOpenHelper extends SQLiteOpenHelper {
private static final String DB_CREATE = "CREATE TABLE " + DB_TABLE
+ " (" + Employee.ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ Employee.NAME + " TEXT NOT NULL, " + Employee.AGE
+ " INTEGER);";
public DBOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(DB_CREATE);
System.err
.println("Verify that the table was created successfully.");
} catch (SQLiteException e) {
e.printStackTrace();
System.err.println("Failed to create table.");
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
/*
* 当你的应用要更新升级的时候,同时新版本中数据库表结构或内容有变化,这时upgrade方法会根据你的数据库版本号来判断数据库是否升级,
* 你可以在upgrade方法中执行数据库的变化。
*/
db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
onCreate(db);
}
}
}
注:有人问onUpgrade(,,)函数会在什么时候调用,这取决于你的版本号是否已经改变,如 public DBOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}中,如果version 改变了,就会执行该函数。
3) AndroidMainfest.xml 文件中加上provider 标签:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mesada.demo.provider"
android:versionCode="1"
android:versionName="1.0">
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<provider
android:name=".EmployeeProvider"
android:authorities="com.mesada.demo.provider.employeeprovider" />
</application>
<uses-sdk
android:minSdkVersion="8" />
</manifest>
4)运行该项目后,即可。这样,ContentProvider 的开发工作已经完成,但它只是封闭了对数据操作的功能,如增删改查等。该项目没有相应的界面显示数据,在下一篇文章《ContentProvider 的使用(2)》说明如何调用ContentProvider,并对其进行增删改查的操作。
如何访问外部应用程序的SharedPreference
示例AccessFromSharePreferenceDemo将说明如何读取其他应用程序(博客中另一项目:DemoSharedPreferences)中保存的SharedPreferences数据
1)新建android项目,项目名称:AccessFromSharePreferenceDemo
2)在继承自Activity的类中编写相应代码:
package com.mesada.demo1;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
/**
* This is a demo about access SharedPreferences.
*
* @author Xiaolong Long
* @date 2010-12-30
* @version 1.0
*/
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private static final boolean mIsPrintInfo = true;
public static final String PREFERENCE_PACKAGE = "com.mesada.demo";
public static final String PREFERENCE_NAME = "MyPrefsFile";
public static final String KEY_USERNAME = "USERNAME";
public static final String KEY_PWD = "PASSWORD";
public static int MODE = Context.MODE_WORLD_READABLE
+ Context.MODE_WORLD_WRITEABLE;
TextView mUserNameView;
TextView mPwdView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
if (mIsPrintInfo)
Log.i(TAG, "onCreate()...");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupControlers();
Context context = null;
try {
context = createPackageContext(PREFERENCE_PACKAGE,
Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
SharedPreferences settings = context.getSharedPreferences(
PREFERENCE_NAME, MODE);
String userName = settings.getString(KEY_USERNAME, "姚明");
String userPwd = settings.getString(KEY_PWD, "123456");
mUserNameView.setText(userName);
mPwdView.setText(userPwd);
}
/**
*
* Find the views that were identified by the id attributes from the XML.
*
* @param
* @return
* @date 2010-12-30
* @author Xiaolong Long
*/
private void setupControlers() {
if (mIsPrintInfo)
Log.i(TAG, "setupControlers()...");
mUserNameView = (TextView) findViewById(R.id.userName);
mPwdView = (TextView) findViewById(R.id.password);
}
}
2.main.xml 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lblusername" />
<TextView
android:id="@+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/lblpassword" />
<TextView
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
3.AndroidMainfest.xml 文件,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mesada.demo1"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>
4)完成。