Android-ContentProvider数据库操作
2013-11-01 23:05
344 查看
在实际的开发过程中,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)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语句时把列名拼错。
(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
MyProvider.java
在同一个应用本身里面(进程)测试插入数据:MainActivity.java
运行结果:
其他应用里面测试(跨进程使用)
TestActivity.java
6.运行过程中遇到的一些问题以及如何解决
解决:不能使用中文的引号
声明的时候掉了一个public final static Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/informations");
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);";
注意空格
代码下载
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进行数据存储
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); }
使用过程中注意三个问题:
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语句时把列名拼错。
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"; }
(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
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
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
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
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)Open quote is expected for attribute "{1}" associated with an element type " android:authorities". android:authorities="com.zlc.provider.MyProvider" /
解决:不能使用中文的引号
(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");
(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);";
注意空格
代码下载
相关文章推荐
- 执行多条SQL语句、Mysql下一些SQL语句
- Oracle发布了51个Java安全补丁
- Oracle创建表空间、创建用户以及授权、查看权限常用sql语句
- SQL 2005创建数据库
- 高性能MySql进化论(六):常见索引类型的原理及其特点的介绍
- 解决VS2010中无法打开类向导(未能打开解决方案的源代码数据库)
- Jorm实现简单的数据库CRUD操作
- sql-server2005下生成定长的随机字符串
- 杂谈---令人抓狂的数据库行级锁问题
- Oracle 块的基本形式
- 论mongodb
- ORACLE正则表达式函数详解--转载整理
- Lsnrctl命令参数
- Oracle中的事务讲解
- Oracle 11g统计信息收集
- listener.ora/sqlnet.ora/tnsnames.ora配置文件详解
- ORACLE package包中的存储过程的定义和使用
- Redis系列-set类型和zset类型
- 字符集问题(Linux、oracle、终端等,导入导出数据)
- SQL-SQL中binary 和 varbinary的区别