在实际的开发过程中,Android提供了5种方式存储数据:
1.文件存储数据
2.使用 Sharedpreferences 存储数据
3.SQLite数据库存储数据
4.使用ContentProvider存储数据
5.网络存储数据
首先我们先简单了解下文件、SharedPreferred如何进行数据存储
1.文件存储操作
文件存储一般存储在sdcard或者ROM,当文件存储在ROM上时,如果是存储在除自己私有空间外(data/data/包名/),在其他地方是需要system系统权限的(http://my.oschina.net/zhoulc/blog/119282)。
文件IO流创建比较简单,就不详述了,在进行文件存储的时候注意两个路径方法就行。
存储到ROM:
Context mContext = XXXActivity.this;
mContext.getFilesDir().getAbsolutePath();
获取路径:/data/data/包名/files
存储到sdCard :
首先判断sdcard是否可用
Environment.getExternalStorageState()是否等于Environment.MEDIA_MOUNTED
Environment.getExternalStorageDirectory().getAbsolutePath()
对sdcard目录操作需要添加权限:
<!-- 添加对SDCARD的写权限 -->
< uses-permission android:name ="android.permission.WRITE_EXTERNAL_STORAGE" >
获取路径:/sdcard
拓展下 :支持u盘的移动设备,u盘一般都是挂载mnt/sda/sdal外设上面
顺带说下以前一直纠结的一个问题:
getApplicationContext() 生命周期是整个应用,应用摧毁它才摧毁
Activity.this的context属于activity ,activity 摧毁他就摧毁
2.通过Sharedpreferences进行数据存储
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<span style=
"line-height:19px;"
>
private
final
static
String PERFS_NAME =
"com.zlc.test"
;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//存放
//第一个参数是存储时的名称,第二个参数则是文件的打开方式(Context.
MODE_PRIVATE)
SharedPreferences userInfo = getSharedPreferences(PERFS_NAME,
0
);
SharedPreferences.Editor editor = userInfo.edit();
editor.putString(
"userName"
,
"zhoulc"
);
editor.putString(
"passWord"
,
"ds"
);
editor.commit();
//读取
System.out.println(
"##########################################"
);
SharedPreferences readInfo = getSharedPreferences(PERFS_NAME,
0
);
String name = readInfo.getString(
"userName"
,
"no_name"
);
String psword = readInfo.getString(
"passWord"
,
"000000"
);
System.out.println(
"name = "
+name+
" password = "
+psword);
}</span>
|
1)getSharedPreferences有两个参数,第一个参数是存储时的名称, 第二个参数则是文件的打开方式(一般使用0或者Context.MODE_PRIVATE)
2)默认的模式为0或MODE_PRIVATE,如果访问其他应用中的Preference,前提条件是:该 preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。
3)千万不要偷懒写成
userInfo.edit().putString("userName", "zhoulc");
userInfo.edit().putString("passWord", "ds");
userInfo.edit().commit();
edit()方法每次都要产生一个新的SharedPreferences.Edit类的对象,所以commit
之后数据没有存储成功。
3.其他几个就不详细介绍了,说下今天的重点ContentProvider
创建一个可对数据库进行操作的ContentProvider我们先要了解涉及到的知识点:
(1)Parcelable(实体类数据一般会用在进程之间通信)
http://my.oschina.net/zhoulc/blog/172163
(2)BaseColumns,这个类只是提供了两个字段,一个是"_id"一个是"_count",便于调用数据库时导致拼写错误,你也可以扩展它,或者自定义这么个,然后直接调用它的常量名,防止写sql语句时把列名拼错。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<span style=
"line-height:19px;"
>
package
android.provider;
public
interface
BaseColumns
{
/**
* The unique ID for a row.
* <P>Type: INTEGER (long)</P>
*/
public
static
final
String _ID =
"_id"
;
/**
* The count of rows in a directory.
* <P>Type: INTEGER</P>
*/
public
static
final
String _COUNT =
"_count"
;
}</span>
|
主要实现三个方法
创建数据库:public DatabaseHelper(Context context)
创建表:public void onCreate(SQLiteDatabase db)
更新表:public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
(4)UriMatcher用来匹配URI。
主要实现两个接口:
添加需要匹配的URI:MATCHER.addURI(String authority, String path, int code) 进行匹配返回定义的value;MATCHER.match(Uri uri)
例:
MATCHER.addURI(Information.AUTHORITY, "informations", INFORMATIONS);
MATCHER.addURI(Information.AUTHORITY, "informations/#", INFORMATION);
# 号为通配符
* 号为任意字符
(5)ContentUris一个工具类,主要是用来处理使用 "content" 约束的Uri对象,经常用到条件查询某个_ID的数据。
主要实现两个接口:
static long parseId(Uri contentUri) 将uri中的id解析出来,此方法返回的是一个long型的id。
static Uri withAppendedId(Uri contentUri, long id)在指定的uri后面添加一条id
为指定参数的记录。
(6)SQLiteDatabase,这个类是核心类,用于管理和操作SQLite数据库,几乎所有的数据库操作,最终都将由这个类完成。
(7)ContentProvider,提供数据库增删改查的接口。
主要实现接口:
public int delete(Uri uri, String selection, String[] selectionArgs)
public String getType(Uri uri)
public Uri insert(Uri uri, ContentValues values)
public boolean onCreate()
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs)
(8)ContentResolver接口和ContentProvider类似,两个区别一个是用户是通过ContentResolver调用ContentProvider提供的接口。
以上类都只是简单介绍,有兴趣的朋友可以去研究下源码和实现过程。这里主要讲使用过程和一些注意细节。
4.ContentProvider 在使用过程中需要注意两点:
(1)在AndroidManifest.xml里面需要注册这个ContentProvider
<provider android:name=".MyProvider" android:authorities="com.zlc.provider.MyProvider" />
(2)当提供给其他进程调用(假如是其他应用),如果当前提供ContentProvider的应用在退出的时候把自己给kill掉了(这个时候ContentProvider也无法使用),则我们需要在AndroidManifest.xml里面再添加一条属性
android:process="com.zlc.provider.MyProvider"
为该组件指定一个不同的默认进程
5.下面贴一下具体实现代码:
(1)ContentProvider提供者TestContentProvider.apk实体类:Information.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
package
com.zlc.provider;
import
android.net.Uri;
import
android.os.Parcel;
import
android.os.Parcelable;
import
android.provider.BaseColumns;
public
class
Information
implements
Parcelable,BaseColumns{
public
final
static
String AUTHORITY =
"com.zlc.provider.MyProvider"
;
public
final
static
Uri CONTENT_URI = Uri.parse(
"content://"
+AUTHORITY+
"/informations"
);
//表字段
public
final
static
String INFO_ID =
"info_id"
;
public
final
static
String INFO_NAME =
"info_name"
;
public
final
static
String INFO_AGE =
"info_age"
;
private
String info_id,info_name,info_age;
public
Information(Parcel source){
info_id = source.readString();
info_name = source.readString();
info_age = source.readString();
}
public
String getInfo_id() {
return
info_id;
}
public
void
setInfo_id(String info_id) {
this
.info_id = info_id;
}
public
String getInfo_name() {
return
info_name;
}
public
void
setInfo_name(String info_name) {
this
.info_name = info_name;
}
public
String getInfo_age() {
return
info_age;
}
public
void
setInfo_age(String info_age) {
this
.info_age = info_age;
}
@Override
public
int
describeContents() {
// TODO Auto-generated method stub
return
0
;
}
@Override
public
void
writeToParcel(Parcel dest,
int
flags) {
// TODO Auto-generated method stub
dest.writeString(info_id);
dest.writeString(info_name);
dest.writeString(info_age);
}
public
final
static
Parcelable.Creator<Information> CREATOR =
new
Parcelable.Creator<Information>() {
@Override
public
Information createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return
new
Information(source);
}
@Override
public
Information[] newArray(
int
size) {
// TODO Auto-generated method stub
return
new
Information[size];
}
};
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
package
com.zlc.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.sqlite.SQLiteDatabase;
import
android.database.sqlite.SQLiteOpenHelper;
import
android.net.Uri;
import
android.provider.BaseColumns;
import
android.util.Log;
public
class
MyProvider
extends
ContentProvider {
private
SQLiteDatabase sqDb;
private
DatabaseHelper helper;
// 数据库名
private
final
static
String DATABASE_NAME =
"zhoulc.db"
;
// 版本
private
static
final
int
DATABASE_VERSION =
1
;
// 表名
private
static
final
String TABLE_NAME =
"Information"
;
// 创建表的sql语句
private
final
static
String CREATE_TABLE =
"Create table "
+ TABLE_NAME
+
"( "
+Information._ID+
" integer primary key autoincrement,"
+ Information.INFO_ID
+
" TEXT,"
+ Information.INFO_NAME +
" TEXT,"
+ Information.INFO_AGE
+
" TEXT);"
;
// Declaration Datababsehelper
private
static
class
DatabaseHelper
extends
SQLiteOpenHelper {
public
DatabaseHelper(Context context) {
super
(context, DATABASE_NAME,
null
, DATABASE_VERSION);
}
@Override
public
void
onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL(CREATE_TABLE);
}
@Override
public
void
onUpgrade(SQLiteDatabase db,
int
oldVersion,
int
newVersion) {
// TODO Auto-generated method stub
db.execSQL(
"DROP TABLE IF EXISTS"
+ TABLE_NAME);
onCreate(db);
}
}
// UriMatcher add URI
private
static
final
UriMatcher MATCHER =
new
UriMatcher(
UriMatcher.NO_MATCH);
private
final
static
int
INFORMATIONS =
1
;
private
final
static
int
INFORMATION =
2
;
static
{
MATCHER.addURI(Information.AUTHORITY,
"informations"
, INFORMATIONS);
MATCHER.addURI(Information.AUTHORITY,
"informations/#"
, INFORMATION);
}
@Override
public
int
delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
sqDb = helper.getWritableDatabase();
int
count =
0
;
switch
(MATCHER.match(uri)) {
case
INFORMATIONS:
count = sqDb.delete(TABLE_NAME, selection, selectionArgs);
break
;
default
:
throw
new
IllegalArgumentException(
"Unkwon Uri:"
+ uri.toString());
}
return
count;
}
@Override
public
String getType(Uri uri) {
// TODO Auto-generated method stub
switch
(MATCHER.match(uri)) {
case
INFORMATIONS:
return
"vnd.android.cursor.dir/Information"
;
case
INFORMATION:
return
"vnd.android.cursor.item/Information"
;
default
:
throw
new
IllegalArgumentException(
"Unkwon Uri:"
+ uri.toString());
}
}
@Override
public
Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
sqDb = helper.getWritableDatabase();
Uri insertUri =
null
;
long
rowid =
0
;
switch
(MATCHER.match(uri)) {
case
INFORMATIONS:
rowid = sqDb.insert(TABLE_NAME, Information.INFO_ID, values);
insertUri = ContentUris.withAppendedId(uri, rowid);
Log.i(
"zhoulc"
,
"insert record...values:"
+ values.toString());
break
;
default
:
throw
new
IllegalArgumentException(
"Unkwon Uri:"
+ uri.toString());
}
return
insertUri;
}
@Override
public
boolean
onCreate() {
// TODO Auto-generated method stub
helper =
new
DatabaseHelper(getContext());
return
helper ==
null
?
false
:
true
;
}
@Override
public
Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
sqDb = helper.getWritableDatabase();
switch
(MATCHER.match(uri)) {
case
INFORMATIONS:
Cursor cursor = sqDb.query(TABLE_NAME, projection, selection,
selectionArgs,
null
,
null
, sortOrder);
return
cursor;
case
INFORMATION:
//条件查询,
long
id = ContentUris.parseId(uri);
String where = Information._ID +
"="
+ id;
if
(selection !=
null
&& !
""
.equals(selection))
{
where = where +
" and "
+ selection;
}
return
sqDb.query(TABLE_NAME, projection, where, selectionArgs,
null
,
null
, sortOrder);
default
:
throw
new
IllegalArgumentException(
"unknow uri"
+ uri.toString());
}
}
@Override
public
int
update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
sqDb = helper.getWritableDatabase();
int
count =
0
;
switch
(MATCHER.match(uri)) {
case
INFORMATIONS:
count = sqDb.update(TABLE_NAME, values, selection, selectionArgs);
return
count;
default
:
throw
new
IllegalArgumentException(
"unknow uri"
+ uri.toString());
}
}
}
|
在同一个应用本身里面(进程)测试插入数据:MainActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package
com.zlc.provider;
import
android.app.Activity;
import
android.content.ContentValues;
import
android.content.Context;
import
android.content.pm.ApplicationInfo;
import
android.content.pm.PackageManager;
import
android.content.pm.PackageManager.NameNotFoundException;
import
android.net.Uri;
import
android.os.Bundle;
public
class
MainActivity
extends
Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context mContext = MainActivity.
this
;
Uri myUri = Information.CONTENT_URI;
ContentValues values =
new
ContentValues();
values.put(Information.INFO_NAME,
"zhoulc"
);
values.put(Information.INFO_AGE,
"99"
);
getContentResolver().insert(myUri, values);
}
}
|
其他应用里面测试(跨进程使用)
TestActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package
com.zlc.database;
import
android.app.Activity;
import
android.content.ContentResolver;
import
android.content.ContentValues;
import
android.database.Cursor;
import
android.net.Uri;
import
android.os.Bundle;
public
class
TestActivity
extends
Activity {
private
ContentResolver resolver;
public
final
static
String AUTHORITY =
"com.zlc.provider.MyProvider"
;
private
final
static
Uri CONTENT_URIS = Uri.parse(
"content://"
+AUTHORITY+
"/informations"
);
private
final
static
Uri CONTENT_URI = Uri.parse(
"content://"
+AUTHORITY+
"/informations/1"
);
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
resolver = getContentResolver();
//step 1 insert data
ContentValues values =
new
ContentValues();
values.put(
"info_name"
,
"zhoulc"
);
values.put(
"info_age"
,
"24"
);
insert(CONTENT_URIS,values);
//查询
Cursor cursor = query(CONTENT_URI,
null
,
null
,
null
,
null
);
if
(cursor !=
null
){
if
(cursor.moveToFirst()){
int
index[] =
new
int
[]{
cursor.getColumnIndex(
"info_id"
),
cursor.getColumnIndex(
"info_name"
),
cursor.getColumnIndex(
"info_age"
)
};
do
{
System.out.println(cursor.getString(index[
1
]));
System.out.println(cursor.getString(index[
2
]));
}
while
(cursor.moveToNext());
}
}
}
// 该方法用于往ContentProvider添加数据。
public
Uri insert(Uri uri,ContentValues values){
Uri dst = resolver.insert(uri, values);
return
dst;
}
// 该方法用于从ContentProvider删除数据。
public
int
delete(Uri uri,String where, String[] selectionArgs){
int
colums = resolver.delete(CONTENT_URI, where, selectionArgs);
return
colums;
}
// 该方法用于更新ContentProvider中的数据。
public
int
update(Uri uri,ContentValues values, String where, String[] selectionArgs){
int
colums = resolver.update(CONTENT_URI, values, where, selectionArgs);
return
colums;
}
// 该方法用于从ContentProvider中获取数据。
public
Cursor query(Uri uri,String[] projection, String where, String[] selectionArgs, String sortOrder){
Cursor cursor = resolver.query(CONTENT_URI, projection, where, selectionArgs, sortOrder);
return
cursor;
}
}
|
6.运行过程中遇到的一些问题以及如何解决
1
2
3
|
(1)Open quote is expected
for
attribute
"{1}"
associated with an element
type
"
android:authorities".
android:authorities=
"com.zlc.provider.MyProvider"
/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
(2)E
/AndroidRuntime
( 4509): FATAL EXCEPTION: main
E
/AndroidRuntime
( 4509): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.zlc.provider
/com
.zlc.provider.MainActivity}: java.lang.IllegalArgumentException: Unknown URL content:
//com
.zlc.provider.MyProviderinformations
E
/AndroidRuntime
( 4509): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
E
/AndroidRuntime
( 4509): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
E
/AndroidRuntime
( 4509): at android.app.ActivityThread.access$600(ActivityThread.java:141)
E
/AndroidRuntime
( 4509): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
E
/AndroidRuntime
( 4509): at android.os.Handler.dispatchMessage(Handler.java:99)
E
/AndroidRuntime
( 4509): at android.os.Looper.loop(Looper.java:137)
E
/AndroidRuntime
( 4509): at android.app.ActivityThread.main(ActivityThread.java:5041)
E
/AndroidRuntime
( 4509): at java.lang.reflect.Method.invokeNative(Native Method)
E
/AndroidRuntime
( 4509): at java.lang.reflect.Method.invoke(Method.java:511)
E
/AndroidRuntime
( 4509): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E
/AndroidRuntime
( 4509): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E
/AndroidRuntime
( 4509): at dalvik.system.NativeStart.main(Native Method)
E
/AndroidRuntime
( 4509): Caused by: java.lang.IllegalArgumentException: Unknown URL content:
//com
.zlc.provider.MyProviderinformations
E
/AndroidRuntime
( 4509): at android.content.ContentResolver.insert(ContentResolver.java:862)
E
/AndroidRuntime
( 4509): at com.zlc.provider.MainActivity.onCreate(MainActivity.java:17)
E
/AndroidRuntime
( 4509): at android.app.Activity.performCreate(Activity.java:5104)
E
/AndroidRuntime
( 4509): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
E
/AndroidRuntime
( 4509): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
E
/AndroidRuntime
( 4509): ... 11
more
W
/ActivityManager
( 2138): Force finishing activity com.zlc.provider/.MainActivity
D
/dalvikvm
( 2138): GC_FOR_ALLOC freed 596K, 13%
free
7327K
/8412K
, paused 63ms, total 63ms
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
(3)E
/AndroidRuntime
( 5411): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.zlc.provider
/com
.zlc.provider.MainActivity}: android.database.sqlite.SQLiteException: near
"tableInformation"
: syntax error (code 1): ,
while
compiling: Create tableInformation(_id integer primary key autoincrement,info_idTEXT,info_nameTEXT,info_ageTEXT);
E
/AndroidRuntime
( 5411): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
E
/AndroidRuntime
( 5411): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
E
/AndroidRuntime
( 5411): at android.app.ActivityThread.access$600(ActivityThread.java:141)
E
/AndroidRuntime
( 5411): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
E
/AndroidRuntime
( 5411): at android.os.Handler.dispatchMessage(Handler.java:99)
E
/AndroidRuntime
( 5411): at android.os.Looper.loop(Looper.java:137)
E
/AndroidRuntime
( 5411): at android.app.ActivityThread.main(ActivityThread.java:5041)
E
/AndroidRuntime
( 5411): at java.lang.reflect.Method.invokeNative(Native Method)
E
/AndroidRuntime
( 5411): at java.lang.reflect.Method.invoke(Method.java:511)
E
/AndroidRuntime
( 5411): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E
/AndroidRuntime
( 5411): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E
/AndroidRuntime
( 5411): at dalvik.system.NativeStart.main(Native Method)
E
/AndroidRuntime
( 5411): Caused by: android.database.sqlite.SQLiteException: near
"tableInformation"
: syntax error (code 1): ,
while
compiling: Create tableInformation(_id integer primary key autoincrement,info_idTEXT,info_nameTEXT,info_ageTEXT);
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:493)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1663)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1594)
E
/AndroidRuntime
( 5411): at com.zlc.provider.MyProvider$DatabaseHelper.onCreate(MyProvider.java:39)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
E
/AndroidRuntime
( 5411): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
E
/AndroidRuntime
( 5411): at com.zlc.provider.MyProvider.insert(MyProvider.java:92)
E
/AndroidRuntime
( 5411): at android.content.ContentProvider$Transport.insert(ContentProvider.java:201)
E
/AndroidRuntime
( 5411): at android.content.ContentResolver.insert(ContentResolver.java:866)
E
/AndroidRuntime
( 5411): at com.zlc.provider.MainActivity.onCreate(MainActivity.java:17)
E
/AndroidRuntime
( 5411): at android.app.Activity.performCreate(Activity.java:5104)
E
/AndroidRuntime
( 5411): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
E
/AndroidRuntime
( 5411): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
E
/AndroidRuntime
( 5411): ... 11
more
W
/ActivityManager
( 2138): Force finishing activity com.zlc.provider/.MainActivity
|
+ "( _id integer primary key autoincrement," + Information.INFO_ID
+ " TEXT," + Information.INFO_NAME + " TEXT," + Information.INFO_AGE+ " TEXT);";
注意空格