同じように設計されたアプリがいくつかあります。拡張アプリケーションはデータベース接続を保持し、拡張SQLiteOpenHelperはすべてのコードを保持します。
これは、標準のAndroidプロジェクトで使用した場合に機能します。
拡張アプリケーションがライブラリプロジェクトにある場合、クラッシュします。
次のコードは、拡張アプリケーションクラスです。これは、ライブラリプロジェクトにあります。ライブラリプロジェクトで使用するとクラッシュしますが、ライブラリプロジェクトのない標準のAndroidアプリの一部である場合はクラッシュしません。MyApplicationクラスをライブラリプロジェクトからプロジェクトに移動しようとしました(マニフェストで名前を変更しました)-成功しませんでした。
私の推測では、ここで釣りをしているだけですが、MySQLiteOpenHelperは、プロジェクト自体ではなく、ライブラリプロジェクトの権利/許可/場所を使用していると思います。
public class MyApplication extends Application {
private static SQLiteDatabase sqliteDatabase;
private static MySQLiteOpenHelper sqliteOpenHelper;
public static SQLiteDatabase getSqliteDatabase() {
return sqliteDatabase;
}
public static MySQLiteOpenHelper getSqliteOpenHelper() {
return sqliteOpenHelper;
}
@Override
public void onCreate() {
super.onCreate();
MyPreferenceActivity.createSettings(getApplicationContext());
sqliteOpenHelper = new MySQLiteOpenHelper(getApplicationContext());
if (sqliteOpenHelper != null) {
sqliteDatabase = sqliteOpenHelper.getWritableDatabase();
}
}
}
これは、拡張SQLiteOpenHelperクラスの一部です。
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
private static final int DATABASEVERSION = 18;
private static final String DATABASENAME = "myproduct.db";
private Context context;
private SQLiteDatabase sqliteDatabase;
private String location;
public MySQLiteOpenHelper(final Context context) {
super(context, DATABASENAME, null, DATABASEVERSION);
this.context = context;
}
@Override
public SQLiteDatabase getWritableDatabase() {
...
try {
if (Tools.isSDCardWriteable() && (fileSdDbDir.exists() || fileSdDb.exists())) {
// Database on SD-card works perfect
// If I use this to create the internal database it fails here too
location = sdDb;
sqliteDatabase = SQLiteDatabase.openOrCreateDatabase(location, null);
int version = sqliteDatabase.getVersion();
if (version != DATABASEVERSION) {
sqliteDatabase.beginTransaction();
try {
if (version == 0) {
onCreate(sqliteDatabase);
} else {
onUpgrade(sqliteDatabase, version, DATABASEVERSION);
}
sqliteDatabase.setVersion(DATABASEVERSION);
sqliteDatabase.setTransactionSuccessful();
} finally {
sqliteDatabase.endTransaction();
}
}
onOpen(sqliteDatabase);
} else {
// internal database fails to create
location = intDb;
sqliteDatabase = super.getWritableDatabase(); <-- fails
}
} catch (Exception exception) {
if (MyPreferenceActivity.DEBUG) Log.d("Exception", exception.getMessage()); <-- crashes
}
return sqliteDatabase;
}
@Override
public void onCreate(final SQLiteDatabase sqliteDatabase) {
//
}
@Override
public void onUpgrade(final SQLiteDatabase sqliteDatabase, final int oldVersion, final int newVersion) {
//
}
...
}
これは、図書館プロジェクトのマニフェストです。
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.yyy.zzzlib.android" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="11" />
</manifest>
これはプロジェクトマニフェストの一部です:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="preferExternal"
android:versionCode="41"
android:versionName="5.0.3"
package="xxx.yyy.zzz.android" >
<application
...
android:name="xxx.yyy.zzzlib.android.MyApplication" >
...
</application>
...
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="11" />
</manifest>
なぜこれが機能しないのかわかりません。おそらくコンテキストのことですが、エラーはファイルを指しています。手がかりはありません。
このアプローチに何か問題がありますか?標準のAndroidプロジェクト環境で完璧に機能します。
よろしくお願いします。
編集:
StacktraceはLog.dでクラッシュを示していますが、失敗しているのはデータベース呼び出しです。
11-04 17:53:56.143: E/AndroidRuntime(1127): FATAL EXCEPTION: main
11-04 17:53:56.143: E/AndroidRuntime(1127): java.lang.RuntimeException: Unable to create application xxx.yyy.zzzlib.android.MyApplication: java.lang.NullPointerException: println needs a message
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3275)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.ActivityThread.access$2200(ActivityThread.java:117)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:969)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.os.Handler.dispatchMessage(Handler.java:99)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.os.Looper.loop(Looper.java:130)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.ActivityThread.main(ActivityThread.java:3683)
11-04 17:53:56.143: E/AndroidRuntime(1127): at java.lang.reflect.Method.invokeNative(Native Method)
11-04 17:53:56.143: E/AndroidRuntime(1127): at java.lang.reflect.Method.invoke(Method.java:507)
11-04 17:53:56.143: E/AndroidRuntime(1127): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
11-04 17:53:56.143: E/AndroidRuntime(1127): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
11-04 17:53:56.143: E/AndroidRuntime(1127): at dalvik.system.NativeStart.main(Native Method)
11-04 17:53:56.143: E/AndroidRuntime(1127): Caused by: java.lang.NullPointerException: println needs a message
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.util.Log.println_native(Native Method)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.util.Log.d(Log.java:137)
11-04 17:53:56.143: E/AndroidRuntime(1127): at xxx.yyy.zzzlib.android.MySQLiteOpenHelper.getWritableDatabase(MySQLiteOpenHelper.java:1493)
11-04 17:53:56.143: E/AndroidRuntime(1127): at xxx.yyy.zzzlib.android.MyApplication.onCreate(MyApplication.java:27)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
11-04 17:53:56.143: E/AndroidRuntime(1127): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3272)