Android-ContentProvider数据库操作

在实际的开发过程中,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>
    (3)SQLiteOpenHelper,包装了数据库的创建、打开、更新的抽象类,通过实现和使用SQLiteOpenHandle可以隐去数据库打开的之前判断数据库是否需要创建或更新的逻辑。 
            主要实现三个方法 
            创建数据库: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];
         }
     };
}
            MyProvider.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
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
声明的时候掉了一个public final static Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/informations");
?
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
private final static String CREATE_TABLE = "Create table " + TABLE_NAME 
+ "( _id integer primary key autoincrement," + Information.INFO_ID 
+ " TEXT," + Information.INFO_NAME + " TEXT," + Information.INFO_AGE+ " TEXT);"; 
注意空格 

代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值