データベースを統合して、後で取得できるように基本的な連絡先情報を保存して保存する作業をしています。ただし、アプリが起動時にクラッシュするため、テーブルが作成されているかどうかさえ確認できません。
_05-05 16:39:50.671 11631-11631/treehouse.greenlight E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: treehouse.greenlight, PID: 11631
Java.lang.RuntimeException: Unable to start activity ComponentInfo{treehouse.greenlight/treehouse.greenlight.Home_screen}: Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.database.sqlite.SQLiteDatabase Android.content.Context.openOrCreateDatabase(Java.lang.String, int, Android.database.sqlite.SQLiteDatabase$CursorFactory, Android.database.DatabaseErrorHandler)' on a null object reference
at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2205)
at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2255)
at Android.app.ActivityThread.access$800(ActivityThread.Java:142)
at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1203)
at Android.os.Handler.dispatchMessage(Handler.Java:102)
at Android.os.Looper.loop(Looper.Java:136)
at Android.app.ActivityThread.main(ActivityThread.Java:5118)
at Java.lang.reflect.Method.invoke(Native Method)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:794)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:610)
Caused by: Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.database.sqlite.SQLiteDatabase Android.content.Context.openOrCreateDatabase(Java.lang.String, int, Android.database.sqlite.SQLiteDatabase$CursorFactory, Android.database.DatabaseErrorHandler)' on a null object reference
at Android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.Java:224)
at Android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.Java:164)
at treehouse.greenlight.MyDBHandler.addContact(MyDBHandler.Java:54)
at treehouse.greenlight.ContactsFragment.onCreateLoader(ContactsFragment.Java:117)
at Android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.Java:490)
at Android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.Java:499)
at Android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.Java:553)
at treehouse.greenlight.ContactsFragment.onActivityCreated(ContactsFragment.Java:71)
at Android.support.v4.app.Fragment.performActivityCreated(Fragment.Java:1797)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:979)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1138)
at Android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.Java:1120)
at Android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.Java:1929)
at Android.support.v4.app.FragmentActivity.onStart(FragmentActivity.Java:547)
at Android.app.Instrumentation.callActivityOnStart(Instrumentation.Java:1171)
at Android.app.Activity.performStart(Activity.Java:5285)
at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2178)
_
データベースハンドラコード:
_public class MyDBHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "contactsDB.db";
public static final String TABLE_CONTACTS = "contacts";
private Context context;
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_PHONE = "phone";
public static final String COLUMN_STATUS = "status";
public static final String COLUMN_BLURB = "blurb";
public MyDBHandler(Context context, String name,
CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
@Override
public void onCreate (SQLiteDatabase db){
String CREATE_CONTACTS_TABLE = "CREATE TABLE " +
TABLE_CONTACTS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY," + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
+ " TEXT," + ContactsContract.CommonDataKinds.Phone.NUMBER + " INTEGER,"
+ COLUMN_STATUS + " TEXT," + COLUMN_BLURB
+ " TEXT" + ");";
db.execSQL(CREATE_CONTACTS_TABLE);
}
@Override
public void onUpgrade (SQLiteDatabase db,int oldVersion, int newVersion){
db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
onCreate(db);
}
public void addContact(ContactsDb contacts) {
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, contacts.getName());
values.put(COLUMN_PHONE, contacts.getPhone());
values.put(COLUMN_STATUS, contacts.getStatus());
values.put(COLUMN_BLURB, contacts.getBlurb());
SQLiteDatabase db = this.getWritableDatabase();
db.insert(TABLE_CONTACTS, null, values);
}
_
Logcatは、問題はSQLiteDatabase db = this.getWriteableDatabase();
にあると述べています
これも私の問題のあるContactsfragmentです:
_public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private CursorAdapter mAdapter;
private Context context;
TextView idView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create adapter once
Context context = getActivity();
int layout = R.layout.activity_list_item_1;
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-requery! Loader requeries.
mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
}
public void ContactsDb(Context context) {
this.context=context;
}
Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] PROJECTION = {
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts._ID, // _ID is always required
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, // that is what we want to display
Contacts.TIMES_CONTACTED,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// each time we are started use our listadapter
setListAdapter(mAdapter);
// and tell loader manager to start loading
getLoaderManager().initLoader(0, null, this);
}
// columns requested from the database
// and name should be displayed in the text1 textview in item layout
public String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER};
String phone = "0";
int dbPhone = 0;
private final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER};
private final int[] TO = {Android.R.id.text1, dbPhone};
public void newContact (View view) {
MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);
String name = Contacts.DISPLAY_NAME_PRIMARY;
int dbPhone =
Integer.parseInt(phone);
String status ="";
String blurb ="";
ContactsDb contacts =
new ContactsDb(name, dbPhone, status, blurb);
dbHandler.addContact(contacts);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Context context = this.context;
// load from the "Contacts table"
MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);
String name = Contacts.DISPLAY_NAME_PRIMARY;
int phone = Integer.parseInt(ContactsContract.CommonDataKinds.Phone.NUMBER);
String status ="Busy";
String blurb ="N/A";
ContactsDb contacts =
new ContactsDb(name, dbPhone, status, blurb);
dbHandler.addContact(contacts);
// no sub-selection, no sort order, simply every row
// projection says we want just the _id and the name column
return new CursorLoader(getActivity(),
contentUri,
PROJECTION,
ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + Contacts.TIMES_CONTACTED + ">=?", // This is selection string, we're looking for records that HAS_PHONE_NUMBER is 1
new String[]{"1", "0"}, // 1 means that contact has a phone number & 60 is the amount of times contacted (arbitrary - needs to be fixed before release)
null);
}
_
最後に、ContactsDBクラスを次に示します。
_public ContactsDb(String name, int phone, String status, String blurb) {
this._name = name;
this._phone = phone;
this._status = status;
this._blurb = blurb;
_
どんな助けでも大歓迎です-私の問題は私のコンテキストがnullであることにあると思います。 MyDBHandlerファイルで定義したのと同じ理由がわかりません。現在のところ、データベースが作成されていることを確認する方法はありません。データを保持していることは言うまでもありません。
どうぞよろしくお願いいたします。Shyam
インスタンス変数を使用する代わりに、誤ってcontext
ローカル変数を作成したようです。
したがって、context
をMyDBHandler
に渡すとnullになるため、this.getWritableDatabase()
を呼び出すとthis
はnullになります。その結果、ログで確認できるように、NullPointerException
を取得します。
_Caused by: Java.lang.NullPointerException: Attempt to invoke virtual method 'Android.database.sqlite.SQLiteDatabase Android.content.Context.openOrCreateDatabase(Java.lang.String, int, Android.database.sqlite.SQLiteDatabase$CursorFactory, Android.database.DatabaseErrorHandler)' on a null object reference
at Android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.Java:224)
at Android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.Java:164)
_
すべてのContext
関連コードをonActivityCreated()
に移動して、有効なContext
があることを確認し、ローカル変数の代わりにインスタンス変数を使用してください。
_public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
private CursorAdapter mAdapter;
private Context context; //this is the Context you will use
TextView idView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create adapter once
//Context context = getActivity(); //Here was the problem
//int layout = R.layout.activity_list_item_1;
//Cursor c = null; // there is no cursor yet
//int flags = 0; // no auto-requery! Loader requeries.
//mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
}
public void ContactsDb(Context context) {
this.context=context;
}
Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] PROJECTION = {
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts._ID, // _ID is always required
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, // that is what we want to display
Contacts.TIMES_CONTACTED,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Add this here:
context = getActivity(); //use the instance variable
int layout = R.layout.activity_list_item_1;
Cursor c = null; // there is no cursor yet
int flags = 0; // no auto-requery! Loader requeries.
mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);
// each time we are started use our listadapter
setListAdapter(mAdapter);
// and tell loader manager to start loading
getLoaderManager().initLoader(0, null, this);
}
// columns requested from the database
// and name should be displayed in the text1 textview in item layout
public String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER};
String phone = "0";
int dbPhone = 0;
private final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER};
private final int[] TO = {Android.R.id.text1, dbPhone};
public void newContact (View view) {
//context should now be valid:
MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1);
String name = Contacts.DISPLAY_NAME_PRIMARY;
int dbPhone =
Integer.parseInt(phone);
String status ="";
String blurb ="";
ContactsDb contacts =
new ContactsDb(name, dbPhone, status, blurb);
dbHandler.addContact(contacts);
}
//........
_
このエラーを解決するには、アダプターのonCreateViewHolderメソッドでdbクラスからオブジェクトを作成します