#android #android-contentprovider
#Android #android-contentprovider
Вопрос:
Я хочу создать базу данных для своего приложения для Android. Я написал код для базы данных в своем проекте; всякий раз, когда я запускаю, он показывает «принудительное закрытие» в эмуляторе. Я пробовал разные способы, но ничего не работает. Где я ошибся?
// EventContentProvider.java
package com.event.test;
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.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
public class EventContentProvider extends ContentProvider {
private static final String DATABASE_NAME = "event.db";
private static final UriMatcher sUriMatcher;
private static final int EVENTS = 1;
private static final int EVENT_ID = 2;
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE event1 (_ID INTEGER PRIMARY KEY, first_name TEXT, last_name TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
private DatabaseHelper mOpenHelper;
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = null;
int count = 0;
try {
db = mOpenHelper.getWritableDatabase();
switch(sUriMatcher.match(uri)){
case EVENTS:
count = db.delete(Event.EVENT_TABLE_NAME, where, whereArgs);
break;
default:
throw new IllegalArgumentException("No content matched");
}
getContext().getContentResolver().notifyChange(uri, null);
} catch(Exception e) {
} finally {
if(db != null)
db.close();
}
return count;
}
@Override
public String getType(Uri uri) {
switch(sUriMatcher.match(uri)){
case EVENTS:
return Event.CONTENT_TYPE;
default:
throw new IllegalArgumentException("No content matched");
}
}
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
long rowId = -1;
Uri contentUri = null;
switch(sUriMatcher.match(uri)){
case EVENTS:
rowId = db.insertOrThrow(Event.EVENT_TABLE_NAME, Event._ID, values);
contentUri = ContentUris.withAppendedId(Event.CONTENT_URI, rowId);
break;
default:
throw new IllegalArgumentException("Unknown URI " uri);
}
db.close();
if(rowId > 0){
return contentUri;
}
return null;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = -1;
try {
switch (sUriMatcher.match(uri)) {
case EVENTS:
rowId = db.update(Event.EVENT_TABLE_NAME, values, selection,
selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " uri);
}
rowId = db.update(Event.EVENT_TABLE_NAME, values, selection,
selectionArgs);
} catch (Exception e) {
} finally {
if(db != null)
db.close();
}
return (int) rowId;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch(sUriMatcher.match(uri)){
case EVENTS:
qb.setTables(Event.EVENT_TABLE_NAME);
qb.setProjectionMap(Event.sEventProjectionMap);
break;
default:
throw new IllegalArgumentException("No content matched in query ");
}
SQLiteDatabase db = null;
Cursor c = null;
try {
db = mOpenHelper.getReadableDatabase();
c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
} catch (Exception e) {
}
return c;
}
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(Event.AUTHORITY, "events", EVENTS);
sUriMatcher.addURI(Event.AUTHORITY, "events/#", EVENT_ID);
}
}
//Event.java
package com.event.test;
import java.util.HashMap;
import android.net.Uri;
import android.provider.BaseColumns;
public class Event implements BaseColumns{
public static final String AUTHORITY = "com.event.data.contentprovider";
public static final Uri CONTENT_URI = Uri.parse("content://com.event.data.contentprovider/events");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.event.event";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.event/vnd.event.event";
public static final String EVENT_TABLE_NAME = "event1";
public static final String FIRSTNAME = "first_name";
public static final String LASTNAME = "last_name";
public static String _ID;
public static HashMap<String,String> sEventProjectionMap;
static {
Event.sEventProjectionMap = new HashMap<String,String>();
Event.sEventProjectionMap.put(Event._ID, Event._ID);
Event.sEventProjectionMap.put(Event.FIRSTNAME, Event.FIRSTNAME);
Event.sEventProjectionMap.put(Event.LASTNAME, Event.LASTNAME);
}
}
//manifestfile.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.event.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".EventManagementActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:name="com.event.test.EventContentProvider"
android:authorities="com.event.data.contentprovider" />
</application>
</manifest>
//EventManagementActivity.java
package com.event.test;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class EventManagementActivity extends Activity implements OnClickListener{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.btn01);
btn.setText("Press Me");
btn.setOnClickListener(this);
}
@Override
public void onClick(View arg0)
{
switch(arg0.getId()){
case R.id.btn01:
ContentValues cv = new ContentValues();
cv.put(Event.FIRSTNAME, "DATTA");
cv.put(Event.LASTNAME, "Prabhu");
getContentResolver().insert(Event.CONTENT_URI, cv);
String[] str = {Event.FIRSTNAME, Event.LASTNAME};
String where = Event.FIRSTNAME " = ? AND "
Event.LASTNAME " = ?";
String [] whereArgs = {"Datta", "Prabhu"};
Cursor c = getContentResolver().query(Event.CONTENT_URI,
str,
where,
whereArgs,
null);
if (c.moveToFirst() ) {
int id = c.getInt(0);
String firstName = c.getString(0);
String lastName = c.getString(1);
EditText edit = (EditText) findViewById(R.id.edit01);
edit.setText( id firstName " " lastName);
TextView tv = (TextView) findViewById(R.id.text01);
tv.setText(id firstName " " lastName);
}
c.close();
break;
}
}
}
//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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:id="@ id/text01"
/>
<EditText
android:id="@ id/edit01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@ id/btn01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
//R.java
package com.event.test;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class id {
public static final int btn01=0x7f050002;
public static final int edit01=0x7f050001;
public static final int text01=0x7f050000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}
//logcat
10-04 01:12:06.904: DEBUG/MediaScanner(285): total time: 981ms
10-04 01:12:06.984: DEBUG/MediaScannerService(285): done scanning volume internal
10-04 01:12:07.344: DEBUG/dalvikvm(216): GC_CONCURRENT freed 243K, 51% free 2798K/5703K, external 410K/517K, paused 4ms 3ms
10-04 01:12:07.854: DEBUG/dalvikvm(178): GC_EXPLICIT freed 331K, 50% free 2952K/5895K, external 1313K/1400K, paused 64ms
10-04 01:12:12.318: WARN/ActivityManager(73): Activity destroy timeout for HistoryRecord{4072bb18 com.event.test/.EventManagementActivity}
10-04 01:12:15.079: INFO/InputReader(73): Device reconfigured: id=0x0, name=qwerty2, display size is now 240x432
10-04 01:12:15.079: INFO/InputManager-Callbacks(73): No virtual keys found for device qwerty2.
10-04 01:12:15.653: INFO/ARMAssembler(73): generated scanline__00000177:03515104_00001001_00000000 [ 91 ipp] (114 ins) at [0x44325520:0x443256e8] in 1138243 ns
10-04 01:12:16.543: INFO/dalvikvm(73): Jit: resizing JitTable from 512 to 1024
10-04 01:12:18.393: INFO/Process(239): Sending signal. PID: 239 SIG: 9
10-04 01:12:18.403: INFO/ActivityManager(73): Process com.event.test (pid 239) has died.
10-04 01:12:21.153: DEBUG/dalvikvm(178): GC_EXTERNAL_ALLOC freed 61K, 51% free 2947K/5895K, external 1202K/1400K, paused 48ms
10-04 01:12:24.723: INFO/ActivityManager(73): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.event.test/.EventManagementActivity } from pid 178
10-04 01:12:24.773: INFO/ActivityManager(73): Start proc com.event.test for activity com.event.test/.EventManagementActivity: pid=335 uid=10034 gids={}
10-04 01:12:25.253: INFO/ARMAssembler(73): generated scanline__00000177:03515104_00001002_00000000 [ 87 ipp] (110 ins) at [0x443256f0:0x443258a8] in 551089 ns
10-04 01:12:25.303: INFO/ActivityThread(335): Pub com.event.data.contentprovider: com.event.test.EventContentProvider
10-04 01:12:25.583: DEBUG/AndroidRuntime(335): Shutting down VM
10-04 01:12:25.583: WARN/dalvikvm(335): threadid=1: thread exiting with uncaught exception (group=0x40015560)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): FATAL EXCEPTION: main
10-04 01:12:25.594: ERROR/AndroidRuntime(335): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.event.test/com.event.test.EventManagementActivity}: java.lang.NullPointerException
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.os.Handler.dispatchMessage(Handler.java:99)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.os.Looper.loop(Looper.java:123)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread.main(ActivityThread.java:3683)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at java.lang.reflect.Method.invokeNative(Native Method)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at java.lang.reflect.Method.invoke(Method.java:507)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at dalvik.system.NativeStart.main(Native Method)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): Caused by: java.lang.NullPointerException
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at com.event.test.EventManagementActivity.onCreate(EventManagementActivity.java:21)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
10-04 01:12:25.594: ERROR/AndroidRuntime(335): ... 11 more
10-04 01:12:25.603: WARN/ActivityManager(73): Force finishing activity com.event.test/.EventManagementActivity
10-04 01:12:26.123: WARN/ActivityManager(73): Activity pause timeout for HistoryRecord{4070aaa0 com.event.test/.EventManagementActivity}
10-04 01:12:27.503: INFO/Process(335): Sending signal. PID: 335 SIG: 9
10-04 01:12:27.543: WARN/InputManagerService(73): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4073ba40
10-04 01:12:27.874: INFO/ActivityManager(73): Process com.event.test (pid 335) has died.
10-04 01:12:36.575: WARN/ActivityManager(73): Activity destroy timeout for HistoryRecord{4070aaa0 com.event.test/.EventManagementActivity}
Комментарии:
1. есть ли какие-либо сообщения об ошибках в logcat?
2. ребята, пожалуйста, помогите! я вставил коды из разных файлов выше. если вы не в состоянии понять. пожалуйста, сообщите
3. Если вы получаете сообщение об ошибке, вы должны опубликовать его, иначе мы не знаем, что это за ошибка. Трассировка стека в logcat обычно указывает вам точную строку кода, которая вызвала ошибку. winksaville.com/blog/programming/debug-logging-in-android
4. @sameerismyname, практически невозможно найти ошибку в гигантской куче кода без какого -либо сообщения об ошибке. Получаете ли вы трассировку strack? Вы получаете сообщение об отмене? Если вы этого не сделаете, вставляйте операторы печати везде, пока не сможете выяснить, какая конкретная строка не работает.
5. Кстати, я знаю, что вы только начинаете, но в вашем обработчике много специфичного для базы данных кода
onClick
— я думаю, вам было бы проще писать и поддерживать свой код, если вы отделите код базы данных от кода графического интерфейса. Гораздо проще отлаживать процедуры, которые выполняют только одно.
Ответ №1:
Трассировка стека указывает вам точную строку кода, которая вызывает проблему:
at com.event.test.EventManagementActivity.onCreate(EventManagementActivity.java:21)
Хотя трассировка стека может показаться запутанной, она очень полезна. Ключ в том, чтобы просмотреть все классы Android и отследить их до вашего класса:
com.event.test.EventManagementActivity.onCreate(EventManagementActivity.java:21) … 21 означает строку 21.
Исключение нулевого указателя обычно означает, что что-то не создается. Отладьте и выполните пошаговую проверку ваших переменных до этой строки. Вы ссылаетесь на что-то нулевое.
Комментарии:
1. Извините за задержку, надеюсь, это поможет!